Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does PostQuitMessage() goes into WM_DESTROY or WM_CLOSE?

Tags:

c

windows

winapi

I am trying to create a very basic window using the Win32 API and it's been a long time since I've done this.

I think my message loop is okay, but when I close the opened window, the application is still running. It looks like the message loop never gets a WM_QUIT message. However, I am calling PostQuitMessage and a message box confirms I called it.

What is wrong with this minimalist code?

#include <Windows.h>

LRESULT CALLBACK window_proc(HWND hwnd, UINT msg,
        WPARAM w_param, LPARAM l_param) {
    switch (msg) {
    case WM_DESTROY:
        MessageBox(NULL, L"destroy", L"info", MB_OK);
        PostQuitMessage(0);
        break;

    default:
        return DefWindowProc(hwnd, msg, w_param, l_param);
    }

    return 0;
}

int CALLBACK WinMain(HINSTANCE h_instance, HINSTANCE h_prev_instance,
        LPSTR cmd_line, int n_cmd_show) {
    WNDCLASS wnd_class;
    HWND hwnd;
    MSG msg;
    BOOL ret;

    wnd_class.cbClsExtra = 0;
    wnd_class.cbWndExtra = 0;
    wnd_class.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
    wnd_class.hCursor = LoadCursor(NULL, IDC_ARROW);
    wnd_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wnd_class.hInstance = h_instance;
    wnd_class.lpfnWndProc = window_proc;
    wnd_class.lpszClassName = L"MyWindowClass";
    wnd_class.lpszMenuName = NULL;
    wnd_class.style = 0;
    if (!RegisterClass(&wnd_class)) {
        MessageBox(NULL, L"cannot register window class",
            L"error", MB_OK | MB_ICONERROR);
    }

    hwnd = CreateWindow(
        L"MyWindowClass",
        L"",
        WS_OVERLAPPEDWINDOW | WS_VISIBLE,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,
        NULL,
        h_instance,
        NULL
    );

    while ((ret = GetMessage(&msg, hwnd, 0, 0)) != 0) {
        if (ret == -1) {
            MessageBox(NULL, L"error", L"", MB_OK);
        } else {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    MessageBox(NULL, L"quitting now", L"info", MB_OK);

    return msg.wParam;
}

The GetMessage doc says the function returns 0 when it reads a WM_QUIT message. Howcome PostQuitMessage is called and GetMessage never returns 0?

Thank you, Win32 gurus.

like image 763
eepp Avatar asked Jan 26 '13 03:01

eepp


1 Answers

Its your GetMessage() loop.

You're passing your window handle to that loop, thereby filtering out all application-thread messages and only receiving messages to that window. .

Change this:

while ((ret = GetMessage(&msg, hwnd, 0, 0)) != 0) 
//  Note window handle =========^

To this:

while ((ret = GetMessage(&msg, NULL, 0, 0)) != 0) 
//  Note no handle =============^

And your application thread queue should now be monitored by your GetMessage() loop.

Why: GetMessage() invokes can be tailored to monitor a specific window handle's message queue. The application WM_QUIT is not posted to a window handle queue; it is posted to the thread-message queue, which can only pull messages off the queue by using GetMessage() (perhaps PeekMessage() as well, but its been too long for me to remember) with no target window handle to specifically monitor.

like image 97
WhozCraig Avatar answered Oct 06 '22 01:10

WhozCraig