3
votes

When trying to display a simple MessageBox it does not display at all.

Code:

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nCmdShow )
{
    try
    {
        Window wnd( { 50, 50 }, Graphics::ScreenWidth, Graphics::ScreenHeight, "Bat Engine", Graphics::FullScreen );
        throw std::exception( "test" );
    }
    catch( const std::exception& e )
    {
        MessageBox( NULL, e.what(), "Error", MB_ICONWARNING | MB_OK );
    }

    return 0;
}

The return value for MessageBox is IDOK which is supposed to mean I clicked the OK button even though that's not the case. GetLastError also doesn't return any errors.

Furthermore, this only happens if I throw the exception after I initialize my Window. The Window class can be found here: https://github.com/SlidyBat/BatEngine/blob/2a1427265d359949a6f3f5a160d553990656354e/Engine/Window.cpp

After looking around for this issue online I found this answer: https://stackoverflow.com/a/41171505/9094644

Sure enough if I clear the message queue before displaying the message box (like this) it works. The messages that are in the queue when clearing it are WM_QUIT, WM_TIMER and a message with ID 1847 (not sure what that one is).

For now I'm just clearing the message queue before displaying the message box to ensure it works, but it would be nice to find out what exactly I'm doing wrong to cause this.

Thanks.

1
Sounds like something called PostQuitMessage(). Put a breakpoint on that and then look at the stack trace to see what's calling it.Paul Sanders
look like WM_QUIT in your message queue. if you call MessageBox at this time - it just exit. if you remove this WM_QUIT - MessageBox run as usualRbMm
Well, there's no need to trace code, as simply looking into Window class source code reveals that it always posts quit message when destroyed. So such behaviour is "not a bug but feature" ;-)Matt
Thanks! I set a breakpoint and found that it was being called by DestroyWindow in ~Window (or rather that lead to PostQuitMessage being called in my message handler). After commenting out that line the message box displays as expected. <3Slidy
@Slidy DestroyWindow() does not post a WM_QUIT message. Neither does WM_DESTROY when passed to DefWindowProc(). This is because an app can have multiple windows active at a time. Destroying any window should not terminate the app. Only when destroying the "main" window, for instance. So, somewhere in code you have not shown, PostQuitMessage() must be getting called.Remy Lebeau

1 Answers

6
votes

The WM_QUIT message is telling your application to quit. To prevent any modals from eating the message or being processed properly Windows automatically prevents a number of windows from finishing creation if there is a WM_QUIT message in the queue.

The Old New Thing on WM_QUIT and modality

If this is not the behaviour you want, then you need to change your Window class implementation to not PostQuitMessage when it errors / exits.


All credit to @Remy Lebeau for finding the link.