1

While elaborating an answer for another question (by myself), I've come up with the idea of using a MessageBox to report the result of my dialog box. It is a WinAPI modal dialog box created with the DialogBox() function.

However, I noticed that handling WM_DESTROY in the dialog's procedure function will prevent the message box from appearing. I would like to understand the mechanics behind that.

Here's the full code, and the referred message box is at the end, right before return 0:

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <string.h>
#include "resource.h"

INT_PTR CALLBACK DlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;
    // uncomment these and the MessageBox won't show up
    //case WM_DESTROY:
        //PostQuitMessage(0);
        //break;
    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case IDOK:
            if (MessageBoxW(hwnd, L"Close the window?", L"Confirm", MB_OKCANCEL) == IDOK)
                EndDialog(hwnd, (INT_PTR)wParam);
            break;
        case IDCANCEL:
            MessageBoxW(hwnd, L"Goodbye.", L"Close", MB_OK);
            EndDialog(hwnd, (INT_PTR)TRUE);
            break;
        }
    }
    return (INT_PTR)FALSE;
}

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
    INT_PTR ret = DialogBoxW(NULL, MAKEINTRESOURCEW(IDD_DIALOG1), NULL, DlgProc);

    wchar_t retTxt[10];
    if (ret == IDOK)
        wcscpy(retTxt, L"Alright!");
    else
        wcscpy(retTxt, L"Error");

    MessageBoxW(NULL, retTxt, L"Result", MB_OK);

    return 0;
}
Community
  • 1
  • 1
Marc.2377
  • 7,807
  • 7
  • 51
  • 95

1 Answers1

4

When you use DialogBox rather than DialogBoxParam, the dialog runs its own message loop that handles WM_DESTROY internally. When you post the WM_QUIT message from your dialog procedure you are generating an additional message* that the dialog box won't use, so it remains in your thread's message queue once the DialogBox function returns.

You then call MessageBox, which runs its own message loop. This immediately pulls the WM_QUIT out of the queue, exits the loop and returns before the dialog is even displayed.

(* actually it's not a "real" message - an internal flag is set that indicates quit has been posted - but the effect is the same on the subsequent message loop)

Jonathan Potter
  • 36,172
  • 4
  • 64
  • 79
  • Then I should not call `PostQuitMessage()` from within my function? If you have a link explaining which events are handled internally for dialogs, please share. Thanks! – Marc.2377 Jun 15 '15 at 20:18
  • Probably worth noting `WM_QUIT` via `PostQuitMessage()` is not a *real* "message" sitting the message queue. Like `WM_TIMER`, `WM_PAINT`, and others, it is a status bit (more or less) and a low priority one at that. When someone asks for a message *and* the queue is otherwise-"empty" a `WM_QUIT` will be manufactured and delivered to the requestor. – WhozCraig Jun 15 '15 at 20:20
  • 1
    @WhozCraig If you think it will help the OP's clarity :) – Jonathan Potter Jun 15 '15 at 20:22
  • 3
    It should, as it helps (at least in little) in seeing how that message stays 'stuck' in the thread message queue. Raymond Chen has a good, though brief, somewhat related article about it at [The Old New Thing](http://blogs.msdn.com/b/oldnewthing/archive/2005/11/04/489028.aspx). – WhozCraig Jun 15 '15 at 23:31