关键事件:ProcessCmdKey

我试图在一个小的测试Windows窗体应用程序上发生一些键盘响应,我有一个粗略的解决方案,它是覆盖ProcessCmdKey。 但是,我遇到了几个问题,而且我发现了一些不一致的问题。

不同的事件:有没有办法告诉参数ref Message msg, Keys keyData ,是否是KeyDown,KeyUp或KeyPress?

KeyPress:我看过的任何地方都说KeyPress,即重复的键盘输入,只发生在字符键上,箭头键不是。 但是,事件处理程序被频繁地调用,并且在相同的mannor /具有相同的行为中,箭头键作为字符键。 这是面对KeyPress事件,还是其他什么?

理想情况下,我喜欢在表单级别处理所有键盘事件而不让它们传递给表单上的控件的方法。 但是,所有文档都让我感到困惑,并错过了关键点,因此我无法完成此操作。

欢迎任何这些主题的帮助。 谢谢!

传递给ProcessCmdKey()的Message结构在其Msg属性中包含WINAPI消息号:

  • WM_KEYDOWN0x100 (256),
  • WM_KEYUP0x101 (257),
  • WM_CHAR (大致相当于KeyPress )是0x102 (258),
  • WM_SYSKEYDOWN0x104 (260),
  • WM_SYSKEYUP0x105 (261)。

关于你关于KeyPress的问题,确实非箭头键之类的非字符键不会在内部生成WM_CHAR消息,但是它们会生成WM_KEYDOWN ,并且该消息也会多次发送以便重复输入。

另请注意,我不确定ProcessCmdKey()是否是实现所需目标的正确方法。 该文档将其描述为仅处理main menu command keys and MDI accelerators ,它们可能只是您要捕获的键的子集。 您可能希望覆盖ProcessKeyPreview() ,它处理子控件接收的所有键盘消息。

在表单中覆盖ProcessCmdKey明确旨在允许您在按钮和菜单项中的内置助记符处理之外实现自定义快捷键击处理。

只有在具有焦点的控件获得KeyDown事件并且无论哪个客户端控件具有焦点之前才会调用按键事件。 因此与KeyUp无关,与KeyPress无关。 执行快捷方式function后,在识别密钥时从覆盖返回true。 这可以防止密钥被进一步处理,它不会生成任何KeyDown / Press / Up事件。

使用该方法的msg参数是非常罕见的,msg.Msg值将只是WM_KEYDOWN或WM_SYSKEYDOWN,当用户按住Alt键时产生后一条消息。 您不关心哪个,因为您始终可以从keyData参数获取。 像这样:

  protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { if (keyData == (Keys.Alt | Keys.F)) { // Alt+F pressed doSomething(); return true; } return base.ProcessCmdKey(ref msg, keyData); } 

您可能想要使用|检查的其他修饰符 这里使用的运算符是Keys.Shift和Keys.Control。 所以(Keys.Shift | Keys.Control | Keys.F1)检查Ctrl + Shift + F1。 当您想要执行一些不寻常的操作(例如检查重复键)时,您可以解释msg数据。 检查MSDN文档以获取WM_KEYDOWN通知。 msg.LParam值包含有关键击的一堆信息。

请注意,您只能在此方法中获取虚拟键。 Keys.F是英文键盘布局上的F键,但不一定是用户布局上相同位置的键的相同字母。 支持function键以避免文档问题。

键重复是键盘控制器的一个function,不仅限于键入键。 按住时,箭头和function键肯定会重复。 您想在此方案中忽略KeyPress。 但是如果你为一个同时也是键入键的键(如Keys.F)分配一个快捷键,那么你总是要检查一个修饰键,这样你就不会破坏像TextBox这样的控件。

最后但同样重要的是,不要忘记按钮和菜单项控件中助记符的内置支持。 像&OK一样编写Text属性会产生一个自我记录的快捷方式,而不需要任何代码。 在此示例中,由用户操作,方法是键入Alt + O.