5

我正在尝试使用 Win32 API 创建一个非常基本的窗口,我已经很久没有这样做了。

我认为我的消息循环没问题,但是当我关闭打开的窗口时,应用程序仍在运行。看起来消息循环永远不会收到WM_QUIT消息。但是,我正在打电话PostQuitMessage,一个消息框确认我打电话给它。

这个极简代码有什么问题?

#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文档说该函数在读取消息时返回0 WM_QUIT。HowcomePostQuitMessage被调用并且GetMessage从不返回 0?

谢谢你,Win32 大师。

4

1 回答 1

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()也是,但它太长我记不住了)从队列中拉出消息,没有目标窗口句柄来专门监控。

于 2013-01-26T04:04:26.533 回答