我使用的组件内部有一个KeyDown处理程序,该处理程序发送用户定义的PostMessage(WM_GROUPUNGROUP),并且还具有处理WM_GROUPUNGROUP的自定义消息处理程序。如何拦截用户定义的消息两次?
我希望我的应用程序在执行此消息处理程序后执行某些操作,而无需修改组件代码。
(如何)可以这样做吗?
我使用的组件内部有一个KeyDown处理程序,该处理程序发送用户定义的PostMessage(WM_GROUPUNGROUP),并且还具有处理WM_GROUPUNGROUP的自定义消息处理程序。如何拦截用户定义的消息两次?
我希望我的应用程序在执行此消息处理程序后执行某些操作,而无需修改组件代码。
(如何)可以这样做吗?
实现此目的的一种方法是通过WindowProc
属性。
只需为您想挂钩的实例分配WindowProc
即可提供您自己的窗口过程。您需要复制一份以前的值WindowProc
,以便确保执行原始处理。
大约是这样的:
type
TMyClass = class
....
FOldWindowProc: TWndMethod;
procedure NewWindowProc(var Message: TMessage);
....
end;
重定向你做这个窗口过程:
FOldWindowProc := SomeControl.WindowProc;
SomeControl.WindowProc := NewWindowProc;
然后实现这样新的窗口过程:
procedure TMyClass.NewWindowProc(var Message: TMessage);
begin
FOldWindowProc(Message);
if Message.Msg = WM_GROUPUNGROUP then
....
end;
当您完成了控制,将旧窗口过程重新放回原位:
SomeControl.WindowProc := FOldWindowProc;
另一种方法是利用消息排队的事实。您可以添加一个Application.OnMessage
处理程序,很可能通过使用TApplicationEvents
对象。这将查看所有排队的消息。但是,OnMessage
在将消息分发到控件之前触发,这听起来像是对您而言可能是错误的方式。
谢谢,这很好。我在我的FormCreate中挂接组件的WindowProc,并保持它干净重新分配给FormDestroy中的FOldWindowPoc。 –
您可以将'processed'设置为true,并手动在OnMessage处理程序中分派消息(DispatchMessage),然后在执行顺序非常重要时执行您的工作。 –
为该组件创建一个插入器类,捕获该WM_GROUPUNGROUP消息并触发一个新事件,例如您将在应用程序中绑定的“OnGroupUngroup”。 – TLama
@TLama这只有在你可以介入所有实例化时才有效 –
@David,我没有得到你的记录。如果您可以按照您的建议更改'WindowProc',为什么您无法将一个单元(包含该拦截器)添加到uses子句中?而且这种拦截将适用于该特定单位的一次和全部实例。 – TLama