PostQuitMessage()是进入WM_DESTROY还是WM_CLOSE?

时间:2013-01-26 03:31:09

标签: c windows winapi

我正在尝试使用Win32 API创建一个非常基本的窗口,自从我完成此操作已经很长时间了。

我认为我的消息循环没问题,但是当我关闭打开的窗口时,应用程序仍在运行。看起来消息循环永远不会收到WM_QUIT消息。但是,我正在呼叫PostQuitMessage并且一个消息框确认我已将其称为。<​​/ p>

这个极简主义代码出了什么问题?

#include <Windows.h>

LRESULT CALLBACK window_proc(HWND hwnd, UINT msg,
        WPARAM w_param, LPARAM l_param) {
    switch (msg) {
    case WM_DESTROY:
        MessageBox(NULL, L"destroy", L"info", MB_OK);
        PostQuitMessage(0);
        break;

    default:
        return DefWindowProc(hwnd, msg, w_param, l_param);
    }

    return 0;
}

int CALLBACK WinMain(HINSTANCE h_instance, HINSTANCE h_prev_instance,
        LPSTR cmd_line, int n_cmd_show) {
    WNDCLASS wnd_class;
    HWND hwnd;
    MSG msg;
    BOOL ret;

    wnd_class.cbClsExtra = 0;
    wnd_class.cbWndExtra = 0;
    wnd_class.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
    wnd_class.hCursor = LoadCursor(NULL, IDC_ARROW);
    wnd_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wnd_class.hInstance = h_instance;
    wnd_class.lpfnWndProc = window_proc;
    wnd_class.lpszClassName = L"MyWindowClass";
    wnd_class.lpszMenuName = NULL;
    wnd_class.style = 0;
    if (!RegisterClass(&wnd_class)) {
        MessageBox(NULL, L"cannot register window class",
            L"error", MB_OK | MB_ICONERROR);
    }

    hwnd = CreateWindow(
        L"MyWindowClass",
        L"",
        WS_OVERLAPPEDWINDOW | WS_VISIBLE,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,
        NULL,
        h_instance,
        NULL
    );

    while ((ret = GetMessage(&msg, hwnd, 0, 0)) != 0) {
        if (ret == -1) {
            MessageBox(NULL, L"error", L"", MB_OK);
        } else {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    MessageBox(NULL, L"quitting now", L"info", MB_OK);

    return msg.wParam;
}

GetMessage doc说该函数在读取WM_QUIT消息时返回0。如何调用PostQuitMessage并且GetMessage永远不会返回0?

谢谢你,Win32大师。

1 个答案:

答案 0 :(得分:8)

它是你的GetMessage()循环。

您将窗口句柄传递给该循环,从而过滤掉所有应用程序线程消息,并仅接收消息到那个窗口。

改变这个:

while ((ret = GetMessage(&msg, hwnd, 0, 0)) != 0) 
//  Note window handle =========^

对此:

while ((ret = GetMessage(&msg, NULL, 0, 0)) != 0) 
//  Note no handle =============^

您的应用程序线程队列现在应该由GetMessage()循环监控。

为什么: GetMessage()调用可以定制以监视特定窗口句柄的消息队列。应用程序WM_QUIT未发布到窗口句柄队列;它被发布到线程消息队列,该队列只能使用GetMessage()(也许PeekMessage()也可以将消息从队列中拉出来,但是对于我来说已经太长了了) no 目标窗口句柄,专门监视。