最近用WinForm做了一个俄罗斯方块的小游戏,其中在处理键盘事件的时候出了点问题,经过查阅资料和反复调试,总结键盘事件如下:
1.键盘事件的响应顺序为KeyDown>KeyPress>KeyUp;
2.KeyDown能响应所有按键,KeyPress能响应除方向键和F1、F2...的其他按键;
3.消息在WndProc处理之前,PreProcessMessage方法会调用多个方法对键盘消息进行预处理;
4.KeyDown的预处理方法:(按执行的先后顺序)
(1)ProcessCmdKey,此方法处理命令键,命令键的优先级高于常规键。 如果此方法返回 true,则将不调度键消息,而且将不发生键事件。 如果此方法返回 false,则将调用IsInputKey.
(2)IsInputKey,如果此方法返回 true,则表示该控件为常规字符,而且将引发KeyDown事件。 如果此方法返回 false,则将调用 ProcessDialogKey。
(3)ProcessDialogKey,此方法处理在控件内实现特殊功能(如在控件及其父级之间切换焦点)的物理按键。 如果中间控件不处理该键,则将调用父控件的 ProcessDialogKey,直至层次结构中的最顶端控件。 如果此方法返回 true,则将完成预处理,而且将不生成按键事件。 如果此方法返回 false,则将发生KeyDown 事件。(我做的程序里面就是这里遇到问题了,窗口上有两个按钮,这时方向键无法响应 KeyDown 事件。重写 ProcessDialogKey 方法后,下断点调试发现父类的同名方法返回值为true,表示已经完成预处理。这里应该是窗口默认的把方向键用来处理按钮的焦点切换,改成直接返回false后可以响应KeyDown事件,但是不能切换按钮的焦点。)
5.KeyPress 的预处理方法:
(1)IsInputChar,如果该字符是普通字符,则此方法返回 true,并且将引发 KeyPress事件,而且不再进行预处理。 否则,将调用 ProcessDialogChar。
(2)ProcessDialogChar,类似于 ProcessDialogKey,将沿控件的层次结构向上调用此方法。 如果控件是容器控件,此方法将通过调用控件及其子控件的 ProcessMnemonic 来检查助记键。 如果 ProcessDialogChar 返回 true,则 KeyPress 事件不会发生。
6.消息在到达WndProc后,会由一组可以重写的方法进行处理,这些方法返回值均为 Boolean。如果返回值为true 表示消息处理完成,它将不传递给基控件或父控件进一步处理,否则,消息将停留在消息队列里,可能有基控件或者父控件进一步处理。
(1)ProcessKeyMessage,此方法处理控件的WndProc方法接受的所有键盘消息。
(2)ProcessKeyPreview,此方法将键盘事件发送到父控件。如果返回值为 true,则不生成键盘事件,否则将调用 ProcessKeyEventArgs
(3)ProcessKeyEventArgs,此方法根据需要引发 KeyDown、KeyPress 和 KeyUp 事件。
以上就是我对WinForm键盘事件的总结。