对于Datagrid的键盘事件响应,我们一定要分辨清楚是Datagrid自身的,还是cell单元格的键盘事件响应,处理方法是有很大区别的。大家可以参考第一篇的方法,对cell中的键盘事件进行处理。
但有个问题上一节没有交待,就是如何对Enter键、方向键、Tab键、Pgup/PgDn这些虚键进行拦截与处理?一般网友遇到这个问题,十有八九是出于这个目的:就是希望按Enter键时使光标在一行中向右一个格一个格跳(从“name”到“123”),而不是立即跳向同一列的下一行(到“xxx”)。(如图1所示)
图1 跳格演示
但是,我们在上一篇中用尽方法也截不下Enter键呀,看来这一键盘响应已经被控件封装为protected型了。控件编写人员把多个预定义的键盘绑定方案封装起来,称为快捷键。我们在Keydown/KeyPress中没办法拦截到Enter键和其它一些键盘按键正是这个原因。
快捷键与菜单快捷方式被称为命令键,应用程序会在对常规输入进行处理前的消息预处理过程中对它们进行处理。命令键也就始终比常规输入键具有优先权。
ProcessCmdKey 方法首先确定控件是否有上下文菜单,如果有,则允许 ContextMenu 处理命令键。如果命令键不是菜单快捷方式,且控件有父级,那么该键传递到父级的 ProcessCmdKey 方法。净效果是命令键在控件层次结构中向上“冒”。除了用户按下的键外,键数据还指示哪些(如果有的话)修改键与该键同时按下。修改键包括 SHIFT、CTRL 和 ALT 键(成为组合键)。
这里要注意:该方法必须返回 true,以指示它已经处理完命令键,或者 false,以指示该键不是命令键。在派生类中重写 ProcessCmdKey 方法时,控件应返回 true 以指示它已处理该键。对于未由该控件处理的键,应返回调用基类的 ProcessCmdKey 方法的结果。
如果不加返回值,会默认为false。这样你明明已经修改了处理方法,却会在执行完你的命令之后,继续执行父类中定义的该键盘按键的处理方法。
那么我们怎么处理文头的命题?解决之道就是自己写一个控件,继承自现有的Datagrid控件,再重写处理命令键响应程序ProcessCmdKey,来实现我们的需求。
步骤一:在vs.net编辑器中,“文件”->“新建”->“项目”,然后选择新建一个“Windows控件库”的项目:HenryDatagrid。这样运行的结果会生成一个DLL文件,而不是EXE执行文件;
步骤二:在HenryDatagrid.vb文件代码编辑窗口中加入有阴影的这句话:
Public Class HenryDatagrid
Inherits System.Windows.Forms.DataGrid ‘这表示新建的控件是Datagrid的派生控件
步骤三:在“类名”窗口中选择overrides,然后在“方法名称”窗口选择“ProcessCmdKey”(如图2所示)
图2 选择要重写的方法
然后就会出现一段空的ProcessCmdKey代码段,我们可以写入自己的代码:
Protected Overrides Function ProcessCmdKey
(ByRef msg As System.Windows.Forms.Message, ByVal keyData As System.Windows.Forms.Keys) As Boolean
Dim WM_KEYDOWN As Integer = 256 ‘消息响应的问题可以参考其他win32编程的文章
Dim WM_SYSKEYDOWN As Integer = 260
If ((msg.Msg = WM_KEYDOWN) Or (msg.Msg = WM_SYSKEYDOWN)) Then
Select Case keyData
Case Keys.Down
MsgBox("截到下箭头键")
Return True
Case Keys.Up
MsgBox("截到上箭头键")
Return True
Case Keys.Enter
SendKeys.Send("{Tab}")
Return True
Case Keys.Control + Keys.M
MsgBox("<CTRL> + m 组合键被截获")
Return True
Case Keys.Alt + Keys.Z
MsgBox("<ALT> + z 组合键被截获")
Return True
End Select
End If
End Function
然后运行一下,生成HenryDatagrid.dll文件
步骤四:再建立一个项目,然后在新项目的设计窗口的工具箱上单击鼠标右键,在弹出菜单中选择“添加引用”,然后在.net选项卡中占击“浏览”,选择到HenryDatagrid.dll,加入进来,然后您的工具箱上会多出一个HenryDatagrid的图标,在新项目中使用HenryDatagrid来代替datagrid控件。看一下,您所需要的“Enter跳格”事件就这样完成了。
建议:您在Keys.Enter代码中的Return True去掉,看一下会有什么情况发生。
这里说句题外话,我们在重写类方法时,必须也只能使用Overridable关键字修饰的Protected
方法。这是因为在VB中是用Overridable 关键字指定属性或方法可以在派生类中重写。没有这个东东的我们
……