为什么 msg.message 在我的程序中不等于 WM_QUIT

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

我有一个使用 peekmessage 而不是 get message 的程序,如果 msg.message 等于 WM_QUIT,它应该会中断,但它永远不会等于,我的程序永远不会结束。

    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);
}

当 window 关闭时 postQuitMessage(); 应该发送 WM_QUIT 消息,但 msg.message 永远不会等于 WM_QUIT

msg.message 是否会WM_QUIT 你测试它的地方是不确定的。

您正在循环查看 PeekMessage 的 return 值。如果消息可用,则 PeekMessage 的 return 值为真。消息队列中可能有不止一条消息,在这种情况下,此循环将处理所有消息。因此,要触发 WM_QUIT 检查,队列中需要 WM_QUIT 消息 并且 它需要是之前队列中的最后一条消息PeekMessage return 为假。有时可能会发生这种情况,但您不能指望它一直发生。

GetMessage() 不同,returns 0WM_QUIT 被检索时,PeekMessage() 只是 returns TRUE任何消息被检索,FALSE否则。只有在 PeekMessage() returns TRUE 时才需要检查 MSG。无法保证 MSGPeekMessage() returns FALSE 时更新。但是您仅在 PeekMessage() returns FALSE.

之后检查 MSG

您需要检查内部 while() 循环中的 MSG,因为这是唯一保证 MSG 包含有效数据的地方,例如:

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;

或者:

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;