代码之家  ›  专栏  ›  技术社区  ›  Dan Byström

设置form.keypreview=true的缺点?

  •  24
  • Dan Byström  · 技术社区  · 15 年前

    我想知道form.keypreview属性到底有什么好处?为什么它存在,我要把它设为真来“冒险”什么?我想一定是 一些 负面影响-否则它根本不应该存在(或者至少在默认情况下是真的)?

    编辑 :我非常清楚 什么 是的。我在问 为什么 . 为什么我必须将其设置为true才能触发键盘事件?为什么键盘事件 总是 为一种形式开火。什么不只是标准行为?

    我问的特殊原因是:我刚刚在我的应用程序的基本表单中设置keypreview=true,所有其他表单都是从它继承来的。我有什么不愉快的惊喜吗?

    3 回复  |  直到 9 年前
        1
  •  63
  •   Noctis    9 年前

    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);
    }
    

    但是 密钥预览 在2000年早期,它被支持帮助大批VB6程序员切换到.NET。 密钥预览 processCmdKey() 允许用户界面响应快捷键。键盘信息通常发送到具有焦点的控件。windows窗体消息循环允许代码在控件看到消息之前先查看该消息。这对于快捷键很重要,实现 KeyDown 事件为 每一个 可能得到焦点来检测它们的控制是非常不切实际的。

    设置 密钥预览 说真的不会引起问题。窗体的 按下 事件将运行,只有当它的代码对击键执行某些操作时,它才会有影响。但请注意,它紧跟着vb6的用法,你看不到用于导航的按键类型。就像光标键和 Tab , Escape Enter 一个对话。没有问题 processCmdKey() .

        2
  •  4
  •   Michal Ciechan    15 年前

    MSDN

    当此属性设置为true时, 表单将接收所有按键, 键控和键控事件。后 表单的事件处理程序已完成 在处理击键时, 然后将击键分配给 集中注意力控制。例如,如果 keypreview属性设置为true 当前选定的控件是 一个文本框,在击键之后 由的事件处理程序处理 文本框控件将接收的窗体 按下的键。处理 仅在窗体级别的键盘事件 不允许控件接收 键盘事件,设置 keypresseventargs.handled属性 窗体的按键事件处理程序 真的。

    您可以使用此属性处理 应用程序中的大多数击键 要么处理击键,要么 调用适当的控件来处理 按键。例如,当 应用程序使用功能键,您 可能需要处理击键 在形式层面而不是写作 每个控件的代码 接收按键事件。

    基本上,当设置为true时,表单可以处理关键事件和控件。

    例如,用户按下k键,调用表单事件处理程序(向下键、向上键、按下键),然后调用当前活动控件上的事件处理程序。

    编辑 :不,没有缺点,也没有令人讨厌的惊喜。我能想到的唯一一件事是性能下降很小,因为它需要检查窗体上的每个keydown、keyup和keypressed的事件句柄。除此之外,除非您将事件处理程序添加到表单中,并执行可能导致问题的操作。你很好。如果您不需要全局处理除控件以外的关键事件,那么我建议您将其保留为false以防止额外的检查。在现代个人电脑上,这不会有明显的区别。

        3
  •  2
  •   Mike Dimmick    9 年前

    标准的windows事件模型是具有键盘焦点的窗口获取所有键盘事件。记住,在windows中,一切都是一个窗口-“控件”只是另一个窗口的子窗口。当按下某些键时,由窗口向其父窗口发送消息(如果它选择这样做)。

    为了使对话框控件之间的导航标准化,windows还提供了“对话框管理器”。在本机代码中,对于模态对话框,这由 DialogBox 功能。对于非模态对话框,您必须调用 IsDialogMessage 在你自己的信息循环中。这就是它如何窃取制表键和光标键来在控件之间导航,并输入以按默认按钮。这与默认情况下不允许控件处理enter相反,而多行编辑控件通常会处理enter。为了发现控件是否要处理密钥,对话框管理器代码将焦点控件 WM_GETDLGCODE 消息;如果控件正确响应,则对话框管理器返回 FALSE 允许 DispatchMessage 要将其实际传递到窗口过程,否则对话框管理器会自己做事情。

    windows窗体基本上只是包装了旧的本机控件,因此它必须符合win32的事件模型。它实现了相同的对话框管理器方法-因此,默认情况下,它不允许您查看tab键、return键和光标键。

    如果要处理其中一个键,建议的方法是重写 PreviewKeyDown 并设置 PreviewKeyDownEventArgs IsInputKey 属性到 true .