Delphi 的KeyPreview是如何工作的?

3xiyfsfu  于 2022-11-04  发布在  其他
关注(0)|答案(4)|浏览(295)

我和一位同事正在讨论哪种方法对系统资源的负担更轻。(注意:这不是我想要答案的问题。相反,标题和下面的粗体行是我想要答案的问题。)

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,并查看消息,然后触发与按键相关的事件。

如果是这样的话,那么这两种方法是不是差不多?

bvpmtnay

bvpmtnay1#

正如其他人已经说过的--可能没有明显的区别。
我只是想指出一篇Peter Below关于这个主题的优秀文章:A Key's Odysseyarchive显示器
本文描述了在 Delphi 2007中为Win32 VCL窗体应用程序实现的关键消息处理。与Delphi 7相比,在这方面有一些变化,但这些主要是我在讨论它们时会强调的新增内容。自Delphi 1时代以来,这些代码的大部分基本上保持不变。对设计的健壮性的致敬。如果你赶时间或者对所有的细节不感兴趣,你可以参考摘要中的大纲来进行精简的概述。

uajslkp6

uajslkp62#

KeyPreview正在运行:

针对目前使用中控件的KeyUp-、KeyDown-和KeyPress-事件行程常式,检查目前使用中表单的KeyPreview属性。例如:在任何控件中按下键都会导致检查窗体的KeyPreview属性。
如果该属性为True,则相关的事件处理程序将在调用自身的事件处理程序之前调用窗体的事件处理程序。如果窗体的事件处理程序未将键值更改为0(或#0,取决于KeyPress或KeyDown/KeyUp),则活动控件的事件处理程序将接管,否则该事件将被视为已处理。

与应用程序比较。OnMessage:

因此,在窗体的事件处理程序中将键值设置为0/#0与设置Application. OnMessage的Handled参数是同义的。在这一点上,实际上没有什么区别。但是,由于OnMessage在调度过程中很早就被调用,因此在性能上有 * 理论上的增益 *,因为消息不会再被调度。当您将Handled设置为False时,根本没有区别。因为KeyPreview属性始终处于选中状态,无论是否设置该属性。
剩下的主要区别是,你必须将所有表单的KeyPreview设置为True,并为所有表单中的每一个实现和维护相应的事件处理程序。将此与Application. OnMessage只有一个事件处理程序进行比较,即:假设您可以对所有表单执行一个例程。

nvbavucw

nvbavucw3#

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

eqoofvh9

eqoofvh94#

这里的底线是,你无法以足够快的速度产生输入信息,让计算机注意到,即使你以比通常快几百甚至几千倍的速度产生输入信息,计算机也不会有问题。
您将无法衡量在OnMessage中处理某个东西与使用KeyPreview之间的差异。
因此,决定使用哪一个是最方便的。如果你需要在应用程序范围内进行处理,并且你没有一个通用的基类来处理所有的窗体,那么你可以使用OnMessage。如果你希望不同的窗体有不同的行为,那么你需要使用KeyPreview
我个人强烈建议进行重构,使项目中的所有表单都派生自一个公共库(TForm的子类)。这将为您提供更大的灵活性。通过这种方式,您可以,例如,使用KeyPreview机制为应用程序中的所有表单应用干预点。
至于KeyPreview是如何实现的,输入消息在KeyDown中被重定向,KeyPress等在TControl中被重定向。要了解更多,请阅读源代码。

相关问题