Почему окно закрывается, а процесс не удаляется после нажатия на крестик?

Рейтинг: 2Ответов: 1Опубликовано: 22.07.2023
#include <windows.h>

int CALLBACK wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR szCmdLine, int nCmdShow)
{
    MSG msg{};
    HWND hwnd{};
    WNDCLASSEX wc{ sizeof(WNDCLASSEX) };
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hbrBackground = reinterpret_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
    wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
    wc.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
    wc.hIconSm = LoadIcon(nullptr, IDI_APPLICATION);
    wc.hInstance = hInstance;
    wc.lpfnWndProc = [](HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)->LRESULT
    {
        switch (uMsg)
        {
            case WM_DESTROY:
            {

                PostQuitMessage(EXIT_SUCCESS);
            }
            return 0;
        }
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    };
    wc.lpszClassName = L"APP";
    wc.lpszMenuName = nullptr;
    wc.style = CS_VREDRAW | CS_HREDRAW;
    if (!RegisterClassEx(&wc))
        return EXIT_FAILURE;
    if (hwnd = CreateWindow(wc.lpszClassName, L"APP", WS_OVERLAPPEDWINDOW, 100, 100, 400, 400, nullptr, nullptr, wc.hInstance, nullptr); hwnd == INVALID_HANDLE_VALUE)
        return EXIT_FAILURE;
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);
    while (GetMessage(&msg, hwnd, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return static_cast<int>(msg.lParam);
}

Ответы

▲ 3Принят

Цикл сообщений организован неправильно.

  1. Он обрабатывает не все сообщения, а только адресованные hwnd.
  2. После того, как окно разрушается (после получения WM_DESTROY), GetMessage перестает получать сообщения и начинает возвращать -1, так как дескриптор окна становится невалидным. Цикл сообщений не прерывается, более того, он начинает раздавать невалидные сообщения.
    for (;;)
    {
        MSG msg{};
        auto const res{GetMessage(&msg, HWND{}, UINT{}, UINT{})};
        if (0 < res)
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
            continue;
        }
        if (res < 0)
        {
            // TODO report error...
        }
        break;
    }