设置Form.KeyPreview = true的缺点?

我不知道Form.KeyPreview属性实际上是好的吗? 为什么它存在,我把我的“风险”设置为真? 我想这肯定会有一些负面影响 – 否则根本不应该存在(或者至less在默认情况下是正确的)?

编辑 :我完全知道它做了什么 。 我在问为什么 。 为什么我必须将它设置为true才能使键盘事件触发? 为什么键盘事件总是不能为表单启动? 标准行为不仅仅是什么?

我问的特别原因是:我刚刚在我的应用程序的基本forms中设置KeyPreview = true,其他所有formsinheritance。 我是否有什么恶心的意外?

Form.KeyPreview是一个时代错误,从表单设计的Visual Basic对象模型继承。 回到VB6时代,您需要KeyPreview才能够实现快捷键击。 这在Windows窗体中不再需要,重写ProcessCmdKey()是更好的解决方案:

 protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { if (keyData == (Keys.Control | Keys.F)) { DoSomething(); // Implement the Ctrl+F short-cut keystroke return true; // This keystroke was handled, don't pass to the control with the focus } return base.ProcessCmdKey(ref msg, keyData); } 

KeyPreview在2000年初被支持帮助VB6程序员的军团转向.NET。 KeyPreviewProcessCmdKey()是让您的用户界面响应快捷键。 键盘消息通常发送到具有焦点的控件。 Windows窗体消息循环允许代码在控件看到它之前查看该消息。 对于快捷键来说,这是非常重要的,对于每个可能让焦点来检测它们的控件来实现KeyDown事件是非常不切实际的。

KeyPreview设置为True不会导致问题。 表单的KeyDown事件将会运行,只有当它有代码来处理按键时才会有影响。 但要小心,它紧跟VB6的使用,你不能看到用于导航的击键类型。 就像光标键和TabEscapeEnter一个对话框一样。 ProcessCmdKey()没有问题。

来自MSDN

当此属性设置为true时,表单将接收所有KeyPress,KeyDown和KeyUp事件。 在表单的事件处理程序完成键击处理之后,将键击分配给具有焦点的控件。 例如,如果将KeyPreview属性设置为true,并且当前选定的控件是TextBox,则按键由事件处理程序处理后,TextBox控件将接收按下的按键。 要仅处理表单级别的键盘事件并且不允许控件接收键盘事件,请将表单的KeyPress事件处理函数中的KeyPressEventArgs.Handled属性设置为true。

您可以使用此属性来处理应用程序中的大部分击键,并处理击键或调用适当的控件来处理击键。 例如,当应用程序使用功能键时,可能需要在表单级别处理键击,而不是为可能接收按键事件的每个控件编写代码。

基本上,当您将其设置为true时,您的表单可以处理关键事件以及您的控件。

EG用户按下K键,调用窗体事件处理程序(按下键,按下键,按下按键),然后调用当前活动控件上的事件处理程序。

编辑 :没有没有缺点或讨厌的惊喜。 我唯一能想到的是性能下降非常小,因为它需要检查每个KeyDown,KeyUp,KeyPressed的窗体上的事件句柄。 除此之外,除非您将事件处理程序添加到表单,并执行可能导致问题的事情。 你很好。 如果您不需要全局处理除控件以外的重要事件,那么我建议您将其设置为false以防止进行额外的检查。 在现代PC上,这不会有明显的差异。

标准的Windows事件模型是具有键盘焦点的窗口获取所有键盘事件。 请记住,在Windows中,一切都是一个窗口 – 一个“控制”只是另一个窗口的子窗口。 如果选择这样做,当某些按键被按下时,就可以通过该窗口向其父母发送消息。

为了标准化对话框上的控件之间的导航,Windows还提供了“对话管理器”。 在本地代码中,对于模态对话框,这由DialogBox函数内部的模态消息循环来处理。 对于无模式对话框,您必须在自己的消息循环中调用IsDialogMessage 这是它如何窃取Tab和光标键在控件之间导航,而Enter则按下默认按钮。 这有相反的效果,即不允许控件默认处理Enter,哪些多行编辑控件通常会处理。 为了发现一个控件是否想要处理一个键,对话管理器代码将焦点控件发送给一个WM_GETDLGCODE消息; 如果控件正确响应,则对话框管理器返回FALSE允许DispatchMessage实际将其传递给窗口过程,否则对话框管理器将自行处理。

Windows窗体很大程度上只是包装旧的本地控件,所以它必须符合Win32的事件模型。 它实现了相同的对话框管理器方法 – 因此,默认情况下,它不允许您查看Tab,Return和光标键。

如果您想要处理其中一个键,推荐的方法是重写PreviewKeyDown并将PreviewKeyDownEventArgs IsInputKey属性设置为true