ker2x
ker2x

Reputation: 450

the WM_CLOSE event is never sent/received?

I'm learning DX12 and, in the process, learning "good old Win32". i have trouble exiting the main loop and it seems related to the fact that i'm not receiving the WM_CLOSE message.

In C++, Windows 10, Console application.

#include <iostream>
#include <d3d12.h>
#include <dxgi1_4.h>
#include <tchar.h>

LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    return ::DefWindowProc(hWnd, msg, wParam, lParam);
}


int main()
{
    std::cout << "Hello World!\n";

    WNDCLASSEX wc = {
        sizeof(WNDCLASSEX),
        CS_CLASSDC,
        WndProc,
        0L, 0L,
        GetModuleHandle(NULL),
        NULL, NULL, NULL, NULL,
        _T("ker engine"),
        NULL
    };

    std::cout << "Registering Class\n";
    ::RegisterClassEx(&wc);

    std::cout << "Creating Window\n";
    HWND hwnd = ::CreateWindow(
        wc.lpszClassName,
        _T("Ker Engine DX12"),
        WS_OVERLAPPEDWINDOW,
        100, 100, 1280, 800, NULL, NULL,
        wc.hInstance, NULL
    );

    std::cout << "Show Window\n";
    ::ShowWindow(hwnd, SW_SHOWDEFAULT);

    std::cout << "Update Window\n";
    ::UpdateWindow(hwnd);

    std::cout << "Entering main loop\n";
    MSG msg;
    ZeroMemory(&msg, sizeof(msg));

    while (msg.message != (WM_QUIT))
    {
        if (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
        {
            ::TranslateMessage(&msg);
            ::DispatchMessage(&msg);
            std::cout << msg.message << std::endl;
            switch (msg.message)
            {
            case WM_CLOSE:
                std::cout << "close received\n";
                ::PostQuitMessage(0);
                break;
            }
            continue;
        }

    }
    std::cout << "leaving main loop\n";

    std::cout << "Destroy Window\n";
    ::DestroyWindow(hwnd);
    std::cout << "Unregister Class\n";
    ::UnregisterClass(wc.lpszClassName, wc.hInstance);
    std::cout << "Bye\n";

    return 0;
}

When i press the X (close) red window button, the window is closed but :

The output is :

Entering main loop
[a lot of message code, in decimal]
160  (a lot of it) (WM_NCMOUSEMOVE)
161  (WM_NCLBUTTONDOWN)
275  (WM_TIMER)
no more output printed, i have to close the console manually.

no WM_CLOSE,or WM_DESTROY, or WM_QUIT. Between BUTTONDOW and whatever TIMER is supposed to be, there should be an event related to the fact that the windows was closed, doesn't it ?

I'm a beginner at this. I tried to search google and stackoverflow but i didn't understand if the context applied to me, or it was too specific/unrelated. it's probably a duplicate but i can't find it.

Am i losing/skiping message perhaps ? that's all i can think of.

Upvotes: 1

Views: 1258

Answers (1)

ker2x
ker2x

Reputation: 450

Thanks to Simon Mourier comment and link to a tutorial, the problem was solved.

The message handling had to be done in WndProc, not in the "main loop".

I'm reposting the modified, cleaned, working, code :

#include <iostream>
#include <d3d12.h>
#include <dxgi1_4.h>
#include <tchar.h>

LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_CLOSE:
        std::cout << "close received\n";
        ::PostQuitMessage(0);
        return 0;
    }
    return ::DefWindowProc(hWnd, msg, wParam, lParam);
}


int main()
{
    WNDCLASSEX wc = {
        sizeof(WNDCLASSEX),
        CS_CLASSDC,
        WndProc,
        0L, 0L,
        GetModuleHandle(NULL),
        NULL, NULL, NULL, NULL,
        _T("ker engine"),
        NULL
    };

    ::RegisterClassEx(&wc);

    HWND hwnd = ::CreateWindow(
        wc.lpszClassName,
        _T("Ker Engine DX12"),
        WS_OVERLAPPEDWINDOW,
        100, 100, 1280, 800, NULL, NULL,
        wc.hInstance, NULL
    );

    ::ShowWindow(hwnd, SW_SHOWDEFAULT);
    ::UpdateWindow(hwnd);

    MSG msg;
    ZeroMemory(&msg, sizeof(msg));
    while (msg.message != (WM_QUIT))
    {
        if (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
        {
            ::TranslateMessage(&msg);
            ::DispatchMessage(&msg);
        }    
    }
    ::DestroyWindow(hwnd);
    ::UnregisterClass(wc.lpszClassName, wc.hInstance);

    return 0;
}

Upvotes: 1

Related Questions