I use an Application.OnMessage event handler to process messages (notifications) from other threads in my program. And I found that if popup menu is active (opened), this event handler is not called. The test code is below (it is without threads but the principle is the same):
procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnMessage := ApplicationEvents1Message;
end;
procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
var Handled: Boolean);
begin
if Msg.message = WM_USER then
Beep();
end;
procedure TForm1.tmr1Timer(Sender: TObject);
begin
PostThreadMessage(GetCurrentThreadId, WM_USER, 0, 0);
end;
OnMessage
is called from the main thread's message loop. This message loop is implemented in Delphi's VCL library code. Hence this library code has the opportunity to call the event handler for OnMessage
.
The popup menu is shown by calling the Win32 function TrackPopupMenuEx
. This function implements a modal message loop to run the tracking UI for the menu. Because this message loop is implemented in Win32 code the VCL code does not have an opportunity to fire the OnMessage
event. The Win32 code knows nothing of the VCL and runs a plain message loop. Messages are serviced and dispatched but no VCL specific code can be executed.
This is a perfect example of why PostThreadMessage
should be avoided. Only if you control every message loop can it be used. Other points of failure include system message dialogs, drag and drop modal loops, window move/size modal loops.
You should stop using PostThreadMesaage
. Instead create a window handle in the main thread using AllocateHWnd
. Post messages to that window from your worker threads.
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