我们在自定义用户控件时常会要封装一些键盘事件,但是如何对Enter键、方向键、Tab键、Pgup/PgDn这些虚键进行拦截与处理成我们的问题,因为这些虚拟键通过KeyDown、KeyPress、KeyUp事件根本拦截不到。
看来这一键盘响应已经被控件封装为protected型了。控件编写人员把多个预定义的键盘绑定方案封装起来,称为快捷键。我们在Keydown/KeyPress中没办法拦截到Enter键和其它一些键盘按键正是这个原因。
快捷键与菜单快捷方式被称为命令键,应用程序会在对常规输入进行处理前的消息预处理过程中对它们进行处理。命令键也就始终比常规输入键具有优先权。
ProcessCmdKey 方法首先确定控件是否有上下文菜单,如果有,则允许 ContextMenu 处理命令键。如果命令键不是菜单快捷方式,且控件有父级,那么该键传递到父级的 ProcessCmdKey 方法。净效果是命令键在控件层次结构中向上“冒”。除了用户按下的键外,键数据还指示哪些(如果有的话)修改键与该键同时按下。修改键包括 SHIFT、CTRL 和 ALT 键(成为组合键)。
这里要注意:该方法必须返回 true,以指示它已经处理完命令键,或者 false,以指示该键不是命令键。在派生类中重写 ProcessCmdKey 方法时,控件应返回 true 以指示它已处理该键。对于未由该控件处理的键,应返回调用基类的 ProcessCmdKey 方法的结果。
如果不加返回值,会默认为false。这样你明明已经修改了处理方法,却会在执行完你的命令之后,继续执行父类中定义的该键盘按键的处理方法。
以下是一个例子:重写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