2010-07-03 60 views
44

我在Windows窗体项目上工作了一段时间,然后决定尝试使用键盘快捷键。一点阅读后,我算了一下,只写一个事件处理程序,并将其绑定到窗体的KeyDown事件:对KeyDown事件没有响应的表单

private void Form1_KeyDown(object sender, KeyEventArgs e) 
{ 
    if (e.Control && e.Alt && e.KeyCode == Keys.O) 
    { 
     MessageBox.Show("Ctrl+Alt+O: magic!"); 
    } 
} 

我这样做,打开Visual Studio设计的属性面板的好醇”的方式,然后双击我的表单的KeyDown事件来生成Form1_KeyDown事件处理程序。但是在测试我的应用程序时,表单完全没有响应。Ctrl + Alt + O键盘快捷键。 Visual Studio设计确实生成的代码虽然到事件处理程序的窗体绑定:

private void InitializeComponent() 
{ 
    // ... 

    this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown); 

    // ... 
} 

于是,我就加入了Console.WriteLine()调用处理程序,以检查它被称为可言,但没有运气无论是。另外,我尝试在事件绑定调用(如上所示)上设置一个断点,并发现程序到达该断点就好了。但是我在方法定义本身中设置的任何断点永远都不会到达。

为了确保我在做正确的前几个步骤,我试着重复他们:

  • 在同解的新形式。
    同一个问题:当我按下Ctrl键+ Alt键+Ø键盘快捷键和调试器甚至没有步入事件处理程序的形式不响应。试了一遍,它的工作原理。

  • 一个全新的WinForms解决方案。
    它完美地工作:消息对话框出现(Console.WriteLine()调用也可以)。

所以我很迷茫。什么阻止了这个项目中的所有表单接收KeyDown事件?

回答

107

您的窗体是否将KeyPreview属性设置为true?

Form.KeyPreview物业

获取或设置指示该事件被传递给具有焦点的控制之前,窗体是否将接收键 事件的值。

http://msdn.microsoft.com/en-us/library/system.windows.forms.form.keypreview.aspx

+0

不,所以我改变了它,解决了它!感谢您的回答和文档链接。 – BoltClock 2010-07-03 20:28:50

+17

这是一个黑客攻击,可以让VB6程序员快乐。它具有执行顺序问题,而是重写ProcessCmdKey()。 – 2010-07-03 21:31:52

+0

@HansPassant,我找不到任何解释执行顺序问题的东西。 KeyDown + KeyPreview不会看到所有的键,这足以解决问题,但执行顺序问题又是什么? – kdbanman 2015-12-08 23:11:28

17

试试你的窗体上的KeyPreview属性设置为true。这对我注册按键很有帮助。

+0

是的,就是这样!非常感谢。 – BoltClock 2010-07-03 20:28:14

23

建议对StackOverflow上和MSDN 12(包括在这里接受的答案)这个问题最常见的部分是快速和容易:

KeyDown事件被触发,只要一个FormKeyPreview属性设置为true

这足以满足大多数的目的,但它是有风险的,原因有二:

  1. KeyDown处理程序do not see all keys。具体来说,“你不能看到用于导航的按键类型,就像光标键和Tab,Escape和Enter对话框一样。”

  2. 拦截关键事件有几种不同的方式,它们都按顺序发生。 KeyDown处理最后。因此,KeyPreview不是一个预览,事件可能会在途中的几个停止沉默。

(感谢@HansPassant这些点。)

相反,在你的Form覆盖ProcessCmdKey

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { 
    if (keyData == Keys.Up) 
    { 
     // Handle key at form level. 
     // Do not send event to focused control by returning true. 
     return true; 
    } 
    return base.ProcessCmdKey(ref msg, keyData); 
} 

这样一来,所有的按键对于方法可见,和该方法首先可以查看事件。

请注意,您仍然可以控制聚焦控件是否参见KeyDown事件。只需返回true以阻止后续的KeyDown事件,而不是像在KeyDown事件处理程序中那样将KeyPressEventArgs.Handled设置为trueHere是一篇有更多细节的文章。

+1

这是正确的答案,特别是如果您发现PreviewKeyDown根本不会在KeyPreview设置为true时触发。 – Tim 2016-01-27 23:16:59

+0

真的,真的很有帮助。如果可以的话,我会加倍努力!谢谢 – 2017-02-09 15:41:58