0

I am new to programming with the Win32 API, and have been trying to figure out why this application is not returning when I close the window.

#include <windows.h>

LRESULT CALLBACK WindowProc(
    _In_ HWND   hwnd,
    _In_ UINT   uMsg,
    _In_ WPARAM wParam,
    _In_ LPARAM lParam
);

int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd)
{
    // Register window class
    WNDCLASS wc = {};
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = L"Window Class";

    RegisterClass(&wc);

    // Create window
    HWND window = CreateWindowEx(
        0,
        wc.lpszClassName,
        L"Window",
        WS_OVERLAPPEDWINDOW,

        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,

        NULL,
        NULL,
        hInstance,
        NULL
    );

    // Show window
    ShowWindow(window, nShowCmd);

    // Main Program Loop
    MSG msg = {};
    while (msg.message != WM_QUIT)
    {
        if (PeekMessage(&msg, window, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return msg.wParam;
}

LRESULT CALLBACK WindowProc(
    _In_ HWND   hwnd,
    _In_ UINT   uMsg,
    _In_ WPARAM wParam,
    _In_ LPARAM lParam
)
{
    switch (uMsg)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    default:
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
}

I stepped through the code with a debugger and saw that after destroying the window, the value of the message was WM_PAINT, and so the program was continuously looping, but I don't understand why WM_QUIT is not being posted.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Sidharth Saha
  • 93
  • 1
  • 4
  • See https://stackoverflow.com/questions/3155782/what-is-the-difference-between-wm-quit-wm-close-and-wm-destroy-in-a-windows-pr – Alois Kraus Dec 16 '20 at 22:51

2 Answers2

2

By providing window as an argument to PeekMessage you are telling it you only want to retrieve messages posted or sent to that window.

But WM_QUIT is a thread message - it's not associated with any given window. To retrieve it you need to call PeekMessage with nullptr for the window filter.

Jonathan Potter
  • 36,172
  • 4
  • 64
  • 79
  • Also see: [The dangers of filtering window messages](https://devblogs.microsoft.com/oldnewthing/20050209-00/?p=36493) – Remy Lebeau Dec 16 '20 at 23:28
1

In addition to Jonathan Potter's answer, your message loop should be using GetMessage() instead of PeekMessage():

MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

GetMessage() blocks the calling thread until a message arrives, and returns FALSE when WM_QUIT is received and the hWnd parameter is NULL.

By using PeekMessage(), you are running a tight busy loop, and the contents of msg are indeterminate when PeekMessage() returns FALSE when no message is available.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770