In a VCL Forms program, I have a Form that implements a method for handling windows messages and updating some controls on the Form, something like:
procedure OnMsgTest (var Msg: TMessage); message WM_CUSTOMTEST;
I use PostMessage
with a custom message to this Form, using a code like this:
h := FindWindow('TFrmTest', nil);
if IsWindow(h) then begin
PostMessage(h, WM_CUSTOMTEST, 0, 0);
end;
When the Form is instantiated several times, using the above code to send the message, only one Form instance updates the information on the screen. I would like all open and instantiated Forms to receive the message.
An important note: PostMessage
can occur within the Form process itself, but also from another process. So, I believe a loop through the Forms would not work.
What would be the best approach to reach my goal?
You would have to enumerate all running top-level windows, posting the message to each matching window individually. You could use EnumWindows()
or a FindWindow/Ex()
loop for that, but a simpler solution is to use PostMessage(HWND_BROADCAST)
to broadcast a message that is registered with RegisterWindowMessage()
. Only windows that handle the registered message will react to it, other windows will simply ignore it. For example:
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');
Then you can do this when needed:
if WM_CUSTOMTEST <> 0 then
PostMessage(HWND_BROADCAST, WM_CUSTOMTEST, 0, 0);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With