PostMessage用于特定表单的所有实例(ClassName):

时间:2018-01-09 13:57:44

标签: delphi delphi-10.1-berlin

在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可以在Form进程本身内发生,也可以在另一个进程中发生。所以,我认为通过Forms的循环不起作用。

实现目标的最佳方法是什么?

1 个答案:

答案 0 :(得分:9)

您必须枚举所有正在运行的顶级窗口,将消息分别发布到每个匹配的窗口。您可以使用EnumWindows()FindWindow/Ex()循环,但更简单的解决方案是使用PostMessage(HWND_BROADCAST)来广播使用RegisterWindowMessage()注册的消息。只有处理已注册消息的窗口才会对它做出反应,其他窗口只会忽略它。例如:

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