Search code examples
cwinapidesktop-applicationwin32-process

For a Win32 Desktop C application, what is the best way to display messages when a program is ending


As an exercise, I'm trying to write a 100% correct Windows program. To that end, I'm checking the return values of every Win32 API call I use and report to the user if there are any problems.

This generally works fine until the program starts to close... for example:

      case WM_CLOSE:
         {
            MessageBoxA( NULL, "Foo", "Testing", MB_OK );
            DestroyWindow( hWnd );
            MessageBoxA( NULL, "Bar", "Testing", MB_OK );

            break;

Displays Foo but not Bar. I've observed that any MessageBox after DestroyWindow will not render.

I understand the technical reasons for this... My question for StackOverflow is: In a Win32 Desktop C program, what is the best mechanism/design to inform the user about something (Boo, Program ended successfully, whatever...) at the end of the program?

Ideally, I'd like to be able to display a MessageBox just before wWinMain terminates.

Thank you!


Solution

  • I've observed that any MessageBox after DestroyWindow will not render.

    Without seeing the rest of your code, I would guess that you are handling WM_DESTROY to call PostQuitMessage().

    If so, then WM_DESTROY will be processed while DestroyWindow() is still running, thus WM_QUIT will be posted before the 2nd call to MessageBox() is made.

    The internal message loop inside of MessageBox() will thus pick up the WM_QUIT message and discard its dialog window. And, being a good modal dialog function, MessageBox() will re-post the WM_QUIT message so that other message loops higher up on the call stack (like yours) will still be able to exit correctly, thus letting your app terminate correctly.

    Ideally, I'd like to be able to display a MessageBox just before wWinMain terminates.

    So, what is stopping you from doing so? Simply do it after your message loop has already handled the WM_QUIT message, eg:

    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
    {
        ...
        MSG msg;
        while (GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        ...
        MessageBox(...); // <-- here
        return 0;
    }