c - PostQuitMessage() 是否进入 WM_DESTROY 或 WM_CLOSE?

标签 c windows winapi

我正在尝试使用 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 文档说函数在读取 WM_QUIT 消息时返回 0。为什么调用 PostQuitMessageGetMessage 永远不会返回 0?

谢谢您,Win32 专家。

最佳答案

它是您的 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())从队列中拉出消息,但时间太长了让我记住)没有要专门监视的目标窗口句柄。

关于c - PostQuitMessage() 是否进入 WM_DESTROY 或 WM_CLOSE?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14533569/

相关文章:

c - 为什么这个函数在释放内存时总是崩溃?

c++ - 监听 WM_SYSCOMMAND 事件

c - 使用 C 递归删除目录

c - 如何在终端中用c语言打印一组随机字母?

windows - 英雄联盟 : Username for 'https://git.heroku.com' : git

Windows Docker Image 在 Azure(网络应用程序)上不断随机挂起

windows - 如何从 Windows 上的 Perl CGI 脚本派生后台进程?

windows - Win32 命名管道和消息大小限制 - 旧的 64K 限制是否仍然适用?

c - 使用单个指针访问二维数组

c - 如何在这个 C printf 代码中换行?