Nathaniel Smith
Nathaniel Smith

Reputation: 106

Why doesn't msg.message ever equal WM_QUIT in my program

I have a program that uses peekmessage instead of get message and it is supposed to break if msg.message ever equals WM_QUIT but it never equals and my program never ends.

    MSG msg = { };
    while (TRUE)
    {
        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        if (msg.message == WM_QUIT) {
            break;
        }
        if (screen == TITLESCREEN) {
            drawTitleScreen();
        }

        if (screen == GAMESCREEN) {
            drawGameScreen();
        }
    }
    return 0;
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        case WM_DESTROY:
        {
            destroyRecorces();
            PostQuitMessage(0);
            return 0;
        }
        case WM_SIZE:
        {
            if (pRenderTarget != NULL)
            {
                GetClientRect(hwnd, &rc);

                D2D1_SIZE_U size = D2D1::SizeU(rc.right, rc.bottom);
                pRenderTarget->Resize(size);

            }
            return 0;
        }
        case WM_GETMINMAXINFO:
        {
            LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam;
            lpMMI->ptMinTrackSize.x = 300;
            lpMMI->ptMinTrackSize.y = 300;
            return 0;
        }
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

when the window closes postQuitMessage(); is supposed to send a WM_QUIT message but msg.message never equals WM_QUIT

Upvotes: 0

Views: 1133

Answers (2)

Remy Lebeau
Remy Lebeau

Reputation: 595369

Unlike GetMessage(), which returns 0 when WM_QUIT is retrieved, PeekMessage() simply returns TRUE when any message is retrieved, and FALSE otherwise. You have to check the MSG only when PeekMessage() returns TRUE. There is no guarantee that the MSG is updated when PeekMessage() returns FALSE. But you are checking the MSG only after PeekMessage() returns FALSE.

You need to check the MSG inside of your inner while() loop, as that is the only place that the MSG is guaranteed to contain valid data, eg:

MSG msg;
while (true)
{
    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    {
        if (msg.message == WM_QUIT) {
            return 0;
        }
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    if (screen == TITLESCREEN) {
        drawTitleScreen();
    }

    if (screen == GAMESCREEN) {
        drawGameScreen();
    }
}
return 0;

Alternatively:

MSG msg = { };
bool keepLooping = true;
do
{
    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    {
        if (msg.message == WM_QUIT)
        {
            keepLooping = false;
            break;
        }
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    if (!keepLooping) {
        break;
    }

    if (screen == TITLESCREEN) {
        drawTitleScreen();
    }

    if (screen == GAMESCREEN) {
        drawGameScreen();
    }
}
while (true);
return 0;

Upvotes: 3

jwezorek
jwezorek

Reputation: 9525

Whether or not msg.message will ever be WM_QUIT where you test for it is not deterministic.

You are looping on the return value of PeekMessage. The return value of PeekMessage is true if a message was available. More than one message may be in the message queue and in such a case this loop will field all of the messages. Thus, for the WM_QUIT check to fire there would need to be a WM_QUIT message in the queue and it would need to be the last message in the queue before PeekMessage returns false. This may happen sometimes but you can't count on it happening all the time.

Upvotes: 1

Related Questions