1

If I have the following code below, how do I detect when the window has been closed, so I can quit? r never seems to get the value -1 0, and I need to process messages for the entire thread, not just the current window.

HWND hWnd = CreateWindowExW(0, L"Edit", L"My Window", WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT, CW_USEDEFAULT, 300, 200, NULL, NULL, NULL, NULL);
ShowWindow(hWnd, SW_SHOWDEFAULT);
MSG msg;
BOOL r;
while ((r = GetMessageW(&msg, NULL, 0, 0)) != 0)
{
    if (r == -1) { break; }
    TranslateMessage(&msg);
    DispatchMessageW(&msg);
}
user541686
  • 205,094
  • 128
  • 528
  • 886

2 Answers2

3

Waiting for r = -1 is not the way you detect that your window has closed. A return value of -1 is not a normal condition: it indicates that an error has occurred in the message loop.

From the documentation:

Return Value

Type: BOOL

If the function retrieves a message other than WM_QUIT, the return value is nonzero.

If the function retrieves the WM_QUIT message, the return value is zero.

If there is an error, the return value is -1. For example, the function fails if hWnd is an invalid window handle or lpMsg is an invalid pointer. To get extended error information, call GetLastError.

When GetMessage retrieves a WM_QUIT message from the queue, it will return a value of 0, and you should end the loop.

If you just want to know when the window has closed, you probably want to handle either the WM_CLOSE or WM_DESTROY messages. For a discussion of these messages, see the answers to this question: What is the difference between WM_QUIT, WM_CLOSE, and WM_DESTROY in a windows program?

Community
  • 1
  • 1
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • 1
    Sorry, I totally forgot `r == -1` isn't the close condition. But isn't it also supposed to exit with `r == 0`? How come it's not doing that? (By the way, I `WM_QUIT` is never sent to the loop.) – user541686 Feb 04 '11 at 00:46
  • @Mehrdad: Yes, my answer addressed that `WM_QUIT` is never sent to the message loop. If `GetMessage` retrieves `WM_QUIT`, it returns a value of 0. Presumably, the issue is that you never *send* a `WM_QUIT` message. You need to handle the case when the window is closed, and use the [`PostQuitMessage` function](http://msdn.microsoft.com/en-us/library/ms644945.aspx) to indicate the loop should exit. – Cody Gray - on strike Feb 04 '11 at 01:07
  • Ohh wait... so if I need to send it, and I have multiple windows open with many controls inside each other, how do I know whether I'm the last window open, and so whether I should send it from WndProc? Doesn't keeping track of it become pretty ugly? – user541686 Feb 04 '11 at 01:09
  • 1
    @Mehrdad: Most applications have a "main" window, that exits the program when closed regardless of what other windows are open. If you do have peer windows, just keep count in a global variable. – Ben Voigt Feb 04 '11 at 02:08
0

I found a solution for this: WM_NULL.
The message loop can handle the matter on its own independently of WndProc:

// written in C# 
MSG msg = new MSG();
while (GetMessage(out msg, window, 0, 0))
{
    if ((msg.message == WM_NULL) && !IsWindow(window))
        break;
    TranslateMessage(ref msg);
    DispatchMessage(ref msg);
}
Console.WriteLine("yeah, out of loop ^^");

From my observation: When window is destroyed GetMessage retrieves WM_NULL messages without pause (1st hint) and IsWindow can check the window (affirmation).

Bitterblue
  • 13,162
  • 17
  • 86
  • 124