JerrySoft

导航

给按钮、链接等控件增加快捷键的控件

我们希望能用快捷键代替鼠标点击做一些事情,例如一个典型的应用就是论坛上常用的Ctrl + Enter 快捷发帖子。就以Ctrl+Enter快捷发帖子为例,实质上呢,就是通过js脚本,捕获系统的onkeyup事件,判断event.ctrlKey是否为true并且event.keyCode为13,如果满足这个条件,那么就调用按钮对象的click()方法,等同于用鼠标去点击按钮。写个简单的示例代码:

  <html>

 <head>

  <title> 快捷键提交示例代码 </title>
  <link rel="stylesheet" href='css/style.css' type="text/css">
  <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
  <meta name="author" content="宝玉" />

<script language="JavaScript" type="text/javascript">
<!--
// 快捷键响应
// targetObj: 目标对象,如果满足快捷键条件,触发目标对象的click事件
// ctrlKey: 是否按住了Ctrl组合键
// shiftKey: 是否按住了Shift组合键
// altKey: 是否按住了Alt组合键
// keycode: 按键对应的数值
function Hotkey(event, targetObj, ctrlKey, shiftKey, altKey, keycode)
{
 if (targetObj && event.ctrlKey == ctrlKey && event.shiftKey == shiftKey && event.altKey == altKey && event.keyCode == keycode)
  targetObj.click();
}

上面的脚本可以方便的给指定的按钮加上快捷键。如果现在我们希望应用到我们的服务器端控件当中去,例如Button、Linkbutton、Hyperlink等,因为控件的ID各不相同,而且所对应的快捷键也各不相同,那么我们就需要写一个控件来给他们添加快捷键了。

想想这个控件需要哪些属性?
TargetControlID:string:既然是给其他控件绑定的,那么所要绑定的目标控件ID是少不了了,根据这个控件ID,我们才能确定一个控件,才能知道它输出时的客户端ID,才能根据客户端ID来在脚本里面确定这个对象。
CtrlKey:bool:判断是否用到Ctrl组合键
ShiftKey:bool:判断是否用到Shift组合键
AltKey:bool:判断是否用到Alt组合键
KeyCode:int:和DHTML里面的event.keyCode对应的,例如Enter的keyCode是13。(注:其实这个不是很友好,因为用的时候还要找一下键盘各个按键和keyCode的对应关系,如果结合一个快捷键设置的控件就比较完美了)
Text:string:可能顺便需要一点文字说明什么的

function fnKeyup(event)
{
 var b = document.getElementById("myButton");
 Hotkey(event, b, true, false, false, 13);
}

// 捕获系统的Keyup事件
// 如果是Mozilla系列浏览器
if (document.addEventListener)
 document.addEventListener("keyup",fnKeyup,true);
else
 document.attachEvent("onkeyup",fnKeyup);

//-->
</script>
 </head>
 
  <body>
<form method="get" action="no.aspx">
<input type="submit"  id="myButton"/>
Ctrl + Enter
</form>

  </body>
 
 </html>
 

相对来说,这是一个比较简单的用户自定义控件应用,创建一个名字为HotKey的类,继承自System.Web.UI.Controls。根据目标控件ID查找控件对象:this.cachedTargetControl = this.NamingContainer.FindControl(this.TargetControlID);
根据上面属性,我们就可以生成相应的客户端脚本了,然后在重写控件的OnPreRender事件中使用RegisterClientScriptBlock方法输出脚本。

代码相对比较简单:

using System;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.Design;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;

namespace CommunityServer.Controls
{
    
/// <summary>
    
/// hotkey
    
/// author: dotey
    
/// http://www.communityserver.cn
    
/// </summary>

    public class Hotkey : Control
    
{
        
private static readonly String scriptKey = "CommunityServer.Controls.Hotkey";
        
        
public Hotkey()
        
{
        }


        
protected override void OnPreRender(EventArgs e)
        
{
            
base.OnPreRender (e);

            
string hotkeyFunctionScript = @"
<script>
function Hotkey(event, targetObj, ctrlKey, shiftKey, altKey, keycode)
{
    if (
        targetObj
        && event.ctrlKey == ctrlKey 
        && event.shiftKey == shiftKey 
        && event.altKey == altKey 
        && event.keyCode == keycode
        )
        targetObj.click();
}
</script>
";

            
if ( !Page.IsClientScriptBlockRegistered( scriptKey ) ) 
            
{
                
this.Page.RegisterClientScriptBlock( scriptKey, hotkeyFunctionScript );
            }


            
string key = scriptKey + "-" + targetControl.ClientID;
            
if ( targetControl != null && !Page.IsClientScriptBlockRegistered( key ) ) 
            
{
                
this.Page.RegisterClientScriptBlock( key, CreateScript() );
            }


        }


        
protected override void Render(HtmlTextWriter writer)
        
{
            
base.Render (writer);
            writer.Write(
this.Text);
        }


        
/// <summary>
        
/// 根据属性生成相关脚本
        
/// </summary>
        
/// <returns></returns>

        private string CreateScript()
        
{
            
if ( targetControl == null )
                
return "";

            
string functionName = string.Format("fn{0}Keyup", targetControl.ClientID);

            StringBuilder s 
= new StringBuilder();
            s.Append(
"<script>\n");
            s.AppendFormat(
"function {0}(event)\n", functionName);
            s.Append(
"{\n");
            s.AppendFormat(
"\tvar b = document.getElementById('{0}');\n", targetControl.ClientID);
            s.AppendFormat(
"\tHotkey(event, b, {0}, {1}, {2}, {3});\n", 
                
this.CtrlKey.ToString().ToLower(),
                
this.ShiftKey.ToString().ToLower(),
                
this.AltKey.ToString().ToLower(),
                
this.KeyCode
                );
            s.Append(
"}\n");

            s.Append(
"if (document.addEventListener)\n");
            s.AppendFormat(
"\tdocument.addEventListener('keyup', {0}, true);\n", functionName);
            s.Append(
"else\n");
            s.AppendFormat(
"\tdocument.attachEvent('onkeyup', {0});\n", functionName);
            s.Append(
"</script>\n");

            
return s.ToString();
        }



        
/// <summary>
        
/// 目标控件
        
/// </summary>

        [
        Category(
"Behavior"),
        DefaultValue(
""),
        ]
        
public virtual String TargetControlID 
        
{
            
get 
            
{
                
object savedState = this.ViewState["TargetControlID"];
                
if ( savedState != null ) 
                
{
                    
return (String)savedState; 
                }

                
return "";
            }

            
set 
            
{
                
this.ViewState["TargetControlID"] = value;
                
this.cachedTargetControl = null;
            }

        }


        
/// <summary>
        
/// 根据目标控件的ID来找目标控件对象
        
/// </summary>

        private Control targetControl 
        
{
            
get 
            
{
                
if ( cachedTargetControl == null ) 
                
{
                    
this.cachedTargetControl = this.NamingContainer.FindControl(this.TargetControlID);
                }

                
return this.cachedTargetControl;
            }

        }

        
private Control cachedTargetControl = null;

        
/// <summary>
        
/// 文字说明
        
/// </summary>

        [
        System.ComponentModel.DefaultValue( 
"Caption" ),
        ]
        
public virtual String Text 
        
{
            
get 
            
{

                Object state 
= ViewState["Text"];
                
if ( state != null ) 
                
{
                    
return (String)state;
                }

                
return "";
            }

            
set 
            
{
                ViewState[
"Text"] = value;
            }

        }


        
/// <summary>
        
/// 和DHTML里面的event.keyCode对应的,例如Enter的keyCode是13。
        
/// </summary>
        
/// <remarks>
        
/// 其实这个不是很友好,因为用的时候还要找一下键盘各个按键和keyCode的对应关系,如果结合一个快捷键设置的控件就比较完美了
        
/// </remarks>

        public int KeyCode
        
{
            
get 
            
{
                
int keyCode = 0;
                
try
                
{
                    keyCode 
= Convert.ToInt32(ViewState["KeyCode"]);
                }

                
catch{}

                
return keyCode;
            }

            
set 
            
{
                ViewState[
"KeyCode"] = value;
            }

        }


        
/// <summary>
        
/// 是否使用Alt复合键
        
/// </summary>

        public bool AltKey
        
{
            
get 
            
{
                Object state 
= ViewState["AltKey"];
                
if ( state != null ) 
                
{
                    
return (Boolean)state;
                }

                
return false;
            }

            
set 
            
{
                ViewState[
"AltKey"] = value;
            }

        }


        
/// <summary>
        
/// 是否使用Shift复合键
        
/// </summary>

        public bool ShiftKey
        
{
            
get 
            
{
                Object state 
= ViewState["ShiftKey"];
                
if ( state != null ) 
                
{
                    
return (Boolean)state;
                }

                
return false;
            }

            
set 
            
{
                ViewState[
"ShiftKey"] = value;
            }

        }


        
/// <summary>
        
/// 是否使用Ctrl复合键
        
/// </summary>

        public bool CtrlKey
        
{
            
get 
            
{
                Object state 
= ViewState["CtrlKey"];
                
if ( state != null ) 
                
{
                    
return (Boolean)state;
                }

                
return false;
            }

            
set 
            
{
                ViewState[
"CtrlKey"] = value;
            }

        }


    }

}
最后,调用的时候就比较方便了:
和普通的自定义用户控件一样:
<asp:Button Runat="server" id="PostButton" CssClass="txt3"></asp:Button>
<cs:Hotkey runat="server" TargetControlID="PostButton" KeyCode="13" CtrlKey="True" Text="(Ctrl + Enter)"/>

posted on 2007-01-04 22:30  水-手  阅读(553)  评论(0)    收藏  举报