简体   繁体   English

关闭不发送 WM_QUIT 消息的应用程序?

[英]Closing an app not sending WM_QUIT message?

Having such a simple Win32 app:拥有这样一个简单的 Win32 应用程序:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR pCmdLine, int nCmdShow) {
    ...
    HWND hwnd = CreateWindowEx(0, CLASS_NAME, L"Learn to Program Windows", WS_POPUP | WS_BORDER, 0, 0, 190, 110, nHwnd, NULL, hInstance, NULL);

    if (hwnd != NULL) {
        ShowWindow(hwnd, nCmdShow);
            
        MSG msg;
        while (GetMessage(&msg, NULL, 0, 0) > 0) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);

            if (msg.message == WM_QUIT)                 {
                swprintf_s(msgbuf, _T("WM_QUIT (main)\n"));
                OutputDebugString(msgbuf);
            }
        }
    }
    return 0;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {

        case WM_DESTROY:
            swprintf_s(msgbuf, _T("WM_DESTROY\n"));
            OutputDebugString(msgbuf);
            PostQuitMessage(0);
            return 0;

        case WM_CLOSE:
            swprintf_s(msgbuf, _T("WM_CLOSE\n"));
            OutputDebugString(msgbuf);
            DestroyWindow(hwnd);
            return 0;

        case WM_QUIT:
            swprintf_s(msgbuf, _T("WM_QUIT\n"));
            OutputDebugString(msgbuf);
            return 0;

        case WM_PAINT: {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hwnd, &ps);
            FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
            Example_DrawImage9(hdc);
            EndPaint(hwnd, &ps);
            return 0;
        }
    }

    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

When i do Alt + F4 to close it i get WM_CLOSE, WM_DESTROY but NOT WM_QUIT?当我按 Alt + F4关闭它时,我得到 WM_CLOSE、WM_DESTROY 但不是 WM_QUIT? Why don't I get the WM_QUIT message?为什么我没有收到 WM_QUIT 消息?

Reading documentation at https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-quit :https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-quit阅读文档:

The WM_QUIT message is not associated with a window and therefore will never be received through a window's window procedure. WM_QUIT 消息与 window 无关,因此永远不会通过窗口的 window 过程接收。 It is retrieved only by the GetMessage or PeekMessage functions.它仅由 GetMessage 或 PeekMessage 函数检索。

Do not post the WM_QUIT message using the PostMessage function;不要使用 PostMessage function 发布 WM_QUIT 消息; use PostQuitMessage.使用 PostQuitMessage。

=== Portion after this was added after answer accepted for further clarification === ===在接受答案后添加此部分以进一步澄清===

As others have noted, there are sort of two things going on in the original code submitted.正如其他人所指出的,在提交的原始代码中发生了两件事。 In the message map, there is a switch case entry for WM_QUIT.在消息 map 中,有一个用于 WM_QUIT 的 switch case 条目。 The documentation I quoted shows that the message is not for windows and so the case statement will never get processed.我引用的文档显示该消息不适用于 windows,因此永远不会处理案例语句。

However, there is another issue going on.但是,还有另一个问题正在发生。 Look at the message pumping:看消息抽:

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

    if (msg.message == WM_QUIT)                 {
        swprintf_s(msgbuf, _T("WM_QUIT (main)\n"));
        OutputDebugString(msgbuf);
    }
}

When GetMessage() is called and the WM_QUIT message is the message retrieved in the queue, then the return value from GetMessage() will be zero and so it will immediately exit the while loop.当调用GetMessage()并且 WM_QUIT 消息是在队列中检索到的消息时, GetMessage()的返回值将为零,因此它将立即退出 while 循环。

This is documented at https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmessage这记录在https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmessage

If the function retrieves a message other than WM_QUIT, the return value is nonzero.如果 function 检索到 WM_QUIT 以外的消息,则返回值非零。

If the function retrieves the WM_QUIT message, the return value is zero.如果 function 检索到 WM_QUIT 消息,则返回值为零。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM