我遇到了奇怪的问题。我有 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;
}