特定表单 (ClassName) 的所有实例的 PostMessage:
PostMessage for all instances of a specific form (ClassName):
在 VCL Forms 程序中,我有一个 Form,它实现了一种方法来处理 windows 消息并更新 Form 上的一些控件,例如:
procedure OnMsgTest (var Msg: TMessage); message WM_CUSTOMTEST;
我使用 PostMessage
和此表单的自定义消息,使用如下代码:
h := FindWindow('TFrmTest', nil);
if IsWindow(h) then begin
PostMessage(h, WM_CUSTOMTEST, 0, 0);
end;
当多次实例化Form时,使用上面的代码发送消息,只有一个Form实例更新了屏幕上的信息。我希望所有打开和实例化的表单都能收到消息。
重要说明:PostMessage
可以发生在表单进程本身,也可以来自另一个进程。所以,我相信通过表单循环是行不通的。
实现我的目标的最佳方法是什么?
您必须枚举所有 运行 顶级 windows,将消息分别发布到每个匹配的 window。您可以为此使用 EnumWindows()
或 FindWindow/Ex()
循环,但更简单的解决方案是使用 PostMessage(HWND_BROADCAST)
来广播使用 RegisterWindowMessage()
注册的消息。只有处理已注册消息的 windows 会对此做出反应,其他 windows 会简单地忽略它。例如:
type
TMyForm = class(TForm)
protected
procedure WndProc(var Msg: TMessage); override;
end;
...
var
WM_CUSTOMTEST: UINT = 0;
procedure TMyForm.WndProc(var Msg: TMessage);
begin
if (Msg.Msg = WM_CUSTOMTEST) and (WM_CUSTOMTEST <> 0) then
begin
...
end else
inherited;
end;
initialization
WM_CUSTOMTEST := RegisterWindowMessage('SomeUniqueNameHere');
然后你可以在需要的时候这样做:
if WM_CUSTOMTEST <> 0 then
PostMessage(HWND_BROADCAST, WM_CUSTOMTEST, 0, 0);
在 VCL Forms 程序中,我有一个 Form,它实现了一种方法来处理 windows 消息并更新 Form 上的一些控件,例如:
procedure OnMsgTest (var Msg: TMessage); message WM_CUSTOMTEST;
我使用 PostMessage
和此表单的自定义消息,使用如下代码:
h := FindWindow('TFrmTest', nil);
if IsWindow(h) then begin
PostMessage(h, WM_CUSTOMTEST, 0, 0);
end;
当多次实例化Form时,使用上面的代码发送消息,只有一个Form实例更新了屏幕上的信息。我希望所有打开和实例化的表单都能收到消息。
重要说明:PostMessage
可以发生在表单进程本身,也可以来自另一个进程。所以,我相信通过表单循环是行不通的。
实现我的目标的最佳方法是什么?
您必须枚举所有 运行 顶级 windows,将消息分别发布到每个匹配的 window。您可以为此使用 EnumWindows()
或 FindWindow/Ex()
循环,但更简单的解决方案是使用 PostMessage(HWND_BROADCAST)
来广播使用 RegisterWindowMessage()
注册的消息。只有处理已注册消息的 windows 会对此做出反应,其他 windows 会简单地忽略它。例如:
type
TMyForm = class(TForm)
protected
procedure WndProc(var Msg: TMessage); override;
end;
...
var
WM_CUSTOMTEST: UINT = 0;
procedure TMyForm.WndProc(var Msg: TMessage);
begin
if (Msg.Msg = WM_CUSTOMTEST) and (WM_CUSTOMTEST <> 0) then
begin
...
end else
inherited;
end;
initialization
WM_CUSTOMTEST := RegisterWindowMessage('SomeUniqueNameHere');
然后你可以在需要的时候这样做:
if WM_CUSTOMTEST <> 0 then
PostMessage(HWND_BROADCAST, WM_CUSTOMTEST, 0, 0);