The message loop is blocked when there is focus in the application menu

I am developing an application that looks basically like this:

while (true)
{
    while (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
    {
       TranslateMessage(&Msg);
       DispatchMessage(&Msg);
    }
    DoSomething();
    Sleep(1);
}

      

What I noticed is that DoSomething () is not called when I click on the menu bar (displaying the menu options). I noticed that the call to DispatchMessage blocks the messae loop until I exit the menu bar!

How could I avoid this behavior?

Thank!

+2


source to share


2 answers


The reason is that Windows processes messages when something like an application menu or message box is displayed, and this message loop that Windows uses will not call your method DoSomething()

. This can be difficult to imagine, so I'll try to walk through what's going on:

  • When someone opens your menu, a message is sent to your window telling them to draw the window. DispatchMessage()

    sends a message to yours WndProc

    just like all other messages.
  • Since you are not handling this message, it is passed to Windows (as yours WndProc

    more than likely calls DefWindowProc

    )
  • As a default operation, Windows draws the menu and starts another default message loop that will not call DoSomething()

  • This loop fetches the messages intended for your application and sends them to your application by calling WndProc

    , so your application does not freeze and keeps running (minus the call DoSomething()

    ).
  • When the menu is closed, control will return to your message loop (only at this point the call DispatchMessage()

    from the very beginning will be returned )

In other words, when the menu is displayed, your message loop is replaced with the default which looks like this (for example)

while (GetMessage(&msg, NULL, 0, 0) > 0) {
    TranslateMessage(&msg); 
    DispatchMessage(&msg); 
} 

      



which, as you can see, will not call your method DoSomething()

.

To test this, try pausing your code in the debugger when the menu is not showing and while it is. If you see the column, you will see that when the menu is displayed, the messages are processed by the Windows message connection, not yours.

The only workaround I can think of (no multithreading) is to start a timer and process the message WM_TIMER

by calling DoSomething()

, but that would not be an ideal solution (as I assume you DoSomething()

only intend to call if there are no messages left to process ).

+2


source


Disable translation and sending Msg to a separate stream.

So far DoSomething is independent of Msg dispatch.



Although I can understand why Dispatch is blocking; is this expected normal behavior?

0


source







All Articles