Why Application.OnMessage is not called when popup menu is shown?

delphi, multithreading

Solution

`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.

Problem

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

Original source