Marc.2377
Marc.2377

Reputation: 8754

MessageBox won't work when handling WM_DESTROY event from DialogBox

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;
}

Upvotes: 1

Views: 446

Answers (1)

Jonathan Potter
Jonathan Potter

Reputation: 37192

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)

Upvotes: 4

Related Questions