从任务栏关闭时,GetMessage不会收到WM_QUIT

时间:2018-10-02 09:48:30

标签: c++ winapi getmessage peekmessage

我遇到了奇怪的问题。我有C ++(WinAPI)应用程序,如果通过[X]窗口按钮将其关闭,则一切正常-窗口关闭,应用程序结束。

但是,当我从任务栏按钮上下文菜单中关闭应用程序时,该窗口关闭,但应用程序/进程仍在运行。卡在GetMessage上。

该应用程序仅包含一个窗口。

我的WndProc仅包含WM_DESTROY处理程序,该处理程序在任何情况下都可以正确处理:

switch (message) {
...
case WM_DESTROY:
    PostQuitMessage(0);
    break;

default:
    return DefWindowProc(hWnd, message, wParam, lParam);
}

该应用程序的主循环为:

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

当我从任务栏菜单关闭应用程序时,窗口关闭,但进程仍停留在GetMessage上。就像它不能正确接收WM_QUIT一样。但是,如果我用PeekMessage替换GetMessage,它将从队列中正确读取WM_QUIT。

也只需在GetMessage使它起作用之前添加其他PeekMessage:

while (true) {
    if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
        int res = GetMessage(&msg, NULL, 0, 0);
        if (res) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        } else {
            break;
        }
    }
}

从任务栏菜单关闭应用程序时,为什么没有简单的GetMessage无法正确接收WM_QUIT的原因?

用于重现该问题的最小应用程序代码:

#include "windows.h"

#pragma comment (lib,"user32.lib")

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    switch (message)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        break;

    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }

    return 0;   
}


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    // register Win32 class for this app
    WNDCLASSEX wndClass = { 0 };
    wndClass.cbSize = sizeof(wndClass);
    wndClass.lpszClassName = L"Minimal Window";
    wndClass.hInstance = hInstance;
    wndClass.style = CS_HREDRAW | CS_VREDRAW;
    wndClass.lpfnWndProc = WndProc;
    wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW);

    if (RegisterClassEx(&wndClass)) {
        HWND hWnd = CreateWindowEx(0, wndClass.lpszClassName, L"Minimal", WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, 0, 0, 1024, 480, NULL, NULL, hInstance, NULL);
        ShowWindow(hWnd, SW_SHOW);
        UpdateWindow(hWnd);

        // process window messages
        MSG msg;
        while (GetMessage(&msg, NULL, 0, 0)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }               
    }
    return 0;
}

0 个答案:

没有答案