Я столкнулся со странной проблемой. У меня есть приложение 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 правильно. Но если я заменю GetMessage на PeekMessage, он правильно читает WM_QUIT из очереди.
Также просто добавление дополнительного PeekMessage до того, как GetMessage заставит его работать:
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;
}
Задача ещё не решена.
Других решений пока нет …