【问题标题】:How does Delphi's KeyPreview work?Delphi 的 KeyPreview 是如何工作的?
【发布时间】:2011-06-28 15:46:47
【问题描述】:

我和一位同事正在争论哪种方式对系统资源的负担更小。 (注意:这不是我想要回答的问题。而是标题和下面加粗的行是我寻求答案的问题。)

1. Using KeyPreview to get the keypresses on a form.

2. Using defining an OnMessage procedure and handling it there.

乍一看,KeyPreview 似乎对系统负担更小,因为定义 OnMessage 过程会导致我们的程序检查传入的每条消息。注意我们不关心的消息会导致它在第一个 if 时跳出陈述。最坏的情况是,我们会为每条消息执行一个 if 语句。

但我们想知道 Delphi 如何处理 KeyPreview 属性...我们想知道 Delphi 是否在内部定义了自己的 OnMessage 并查看消息以触发与按键相关的事件。

如果是这种情况,那么这两种方法是否大致相同?

【问题讨论】:

  • 看看源码就知道了。基本上,它使用的是消息处理程序。
  • 我就是这么想的,只是还没想到。
  • 我确定您的意思是 KeyPreview 而不是 OnKeyPreview
  • 我确实做到了。我已经改变了标题。泰。

标签: delphi


【解决方案1】:

正如其他人已经说过的 - 可能没有明显的区别。

我只是想指出一篇 Peter Below 关于该主题的出色文章:A Key's Odyssey

本文描述了关键信息 Delphi 中实现的处理 2007 用于 Win32 VCL 表单应用程序。 这个领域发生了一些变化 与 Delphi 7 相比,但这些是 我将重点介绍的主要内容 当我们找到他们时。大部分代码 此后基本保持不变 Delphi 1 时代,致敬 设计的稳健性。如果你 赶时间或不感兴趣 您可以参考的所有详细信息 简明摘要中的大纲 概览。

【讨论】:

  • +1 啊,彼得在下面。德尔福的乔恩·斯基特。很久没有读到他的东西了。他似乎消失了。
【解决方案2】:

KeyPreview 功能:

为当前活动控件的 KeyUp-、KeyDown- 和 KeyPress- 事件处理程序检查当前活动窗体的 KeyPreview 属性。即:任何控件中的按键都会导致检查表单的 KeyPreview 属性。

如果该属性为 True,则相关事件处理程序会先于其自身调用表单的事件处理程序。如果表单的事件处理程序没有将键值更改为 0(或 #0,取决于 KeyPress 或 KeyDown/KeyUp),则活动控件的事件处理程序会接管,否则该事件被视为已处理。

与 Application.OnMessage 相比:

因此,在表单的事件处理程序中将键值设置为 0/#0 与设置 Application.OnMessage 的 Handled 参数是同义的。在这一点上,几乎没有区别。但是由于 OnMessage 在调度过程中很早就被调用,因此在性能方面存在理论上的增益,因为消息不会被进一步调度。当您将 Handled 设置为 False 时,完全没有区别,因为无论是否设置,始终检查 KeyPreview 属性。

剩下的主要区别是您必须将所有表单的 KeyPreview 设置为 True,并为所有表单中的每一个实施和维护适当的事件处理程序。将此与只有一个用于 Application.OnMessage 的事件处理程序进行比较。那就是:假设您可以对所有表单只使用一个例程。

【讨论】:

    【解决方案3】:

    最好的答案是,测量它。很可能两者都不会给系统带来任何明显的“负担”,如果您在专门寻找它时没有注意到它,那么您的用户也不会注意到它。因此,请选择更容易理解的那个,以防您将来某个时候需要返回该代码。

    【讨论】:

    • +1 感谢您的回答。我同意任何一种方式都可能不引人注意。我在我的问题中更清楚地说明了我真正在寻找什么。
    • 我希望差异可以忽略不计(小得无法衡量),并且无论您编写什么代码来进行处理都是问题,而不是调用您的处理程序。
    • 你不需要测量它。这是微不足道的。您的计算机不会因处理输入消息而紧张。来吧,它可以在每纳秒内完成数百万次的巨型操作。你能打字多快?!!只需选择最适合手头问题的机制
    【解决方案4】:

    这里的底线是您无法快速生成输入以使计算机甚至注意到。如果您以比平时高出数百甚至数千的速度生成输入消息,则计算机不会出现问题。

    您将无法衡量在 OnMessage 中处理某事与使用 KeyPreview 之间的区别。

    所以决定使用哪个最方便。如果您需要在应用程序范围内进行处理,并且您的所有表单都没有公共基类,那么您可以使用OnMessage。如果您想为不同的表单提供不同的行为,那么您需要使用KeyPreview

    我个人强烈建议进行重构,以便项目中的所有表单都派生自一个公共基础(TForm 的子类)。这使您具有更大的灵活性。例如,通过这种方式,您可以使用KeyPreview 机制为应用程序中的所有表单应用干预点。

    至于KeyPreview 是如何实现的,输入消息在TControl 中重定向到KeyDownKeyPress 等。要了解更多信息,请阅读源代码。

    【讨论】:

      猜你喜欢
      • 2014-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多