Confirmation Message Boxes

Introduction

Welcome back to Application Menus and Dialogs. We are now in Lesson 2, which means we already have a working menu from the previous lesson and can start making the app behave more like a real desktop program. In this lesson, we will improve the Exit command so it does not close the window right away.

This small change matters a lot. When an action is important, a good application pauses and asks for confirmation. By the end of this lesson, we will use MessageBoxW to interrupt the flow, ask a clear question, and only close the app when the user truly means it.

Why Confirmation Dialogs Matter

Before we touch the code, let us build the right mental model. A confirmation dialog is useful when an action is hard to undo, such as quitting an app. In WinAPI, MessageBoxW gives us a standard Windows dialog, so we do not need to design a custom window for a simple Yes or No choice.

The key idea is that this dialog is modal: while it is open, the user must respond to it before returning to the main window. That makes it perfect for decisions that should not be ignored.

  1. The app receives a command.
  2. A message box appears and asks for confirmation.
  3. The app checks the result.
  4. The app either continues running or initiates the closing sequence.

Reusing The Menu Structure

As we may recall from the previous unit, the menu setup itself does not change. We still define the same command IDs, open the same window procedure, and build the same File menu during WM_CREATE. That existing structure is what gives us a place to attach the new confirmation step.

C++
#include <windows.h>

#define ID_FILE_OPEN 2001
#define ID_FILE_EXIT 2002

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
        case WM_CREATE: {
            HMENU hMenuBar = CreateMenu();
            HMENU hFileMenu = CreatePopupMenu();
            AppendMenuW(hFileMenu, MF_STRING, ID_FILE_OPEN, L"&Open...");
            AppendMenuW(hFileMenu, MF_SEPARATOR, 0, NULL);
            AppendMenuW(hFileMenu, MF_STRING, ID_FILE_EXIT, L"E&xit");
            AppendMenuW(hMenuBar, MF_POPUP, (UINT_PTR)hFileMenu, L"&File");
            SetMenu(hwnd, hMenuBar);
            return 0;
        }

This part is our foundation:

  1. #include <windows.h> gives access to WinAPI types and functions.
  2. ID_FILE_OPEN and ID_FILE_EXIT are the command IDs we check later.
  3. WM_CREATE builds the menu bar and attaches the File menu to the window.

So, the interface stays the same; what changes is the behavior behind Exit.

Returning To Command Handling

The next step is to revisit WM_COMMAND, because that is where menu clicks arrive. We still use LOWORD(wParam) to extract the selected command ID. The Open command remains a placeholder for now, and the Exit command gets its own block because we are about to add extra logic inside it.

C++
        case WM_COMMAND: {
            switch (LOWORD(wParam)) {
                case ID_FILE_OPEN:
                    break; // Logic for file selection will be added in the next unit

                case ID_FILE_EXIT: {

There are two small but important details here. First, ID_FILE_OPEN does nothing yet on purpose, which keeps the code ready for the next lesson. Second, case ID_FILE_EXIT uses braces {} so we can safely declare a local variable inside that case. That variable will store the result returned by the confirmation dialog.

Showing The Confirmation Message Box

Now we add the core feature of this lesson: a modal confirmation dialog. The MessageBoxW function displays a standard Windows message box and waits until the user chooses a button. Its return value tells us which button was pressed.

C++
                    // Display a modal confirmation dialog to the user
                    int result = MessageBoxW(
                        hwnd,                              // Parent window
                        L"Are you sure you want to quit?", // Dialog text
                        L"Exit Confirmation",              // Dialog title
                        MB_YESNO | MB_ICONQUESTION         // Buttons and icon
                    );

Each argument has a clear role:

  1. hwnd: makes the message box belong to our main window.
  2. The text asks the actual question.
  3. The title labels the dialog clearly.
  4. MB_YESNO | MB_ICONQUESTION combines two style flags, so the dialog shows Yes and No buttons plus a question icon.

We can also change the available buttons by swapping MB_YESNO with other style flags:

  • MB_OKCANCEL: Shows OK and Cancel buttons.
  • MB_RETRYCANCEL: Shows Retry and Cancel buttons.
  • MB_YESNOCANCEL: Shows Yes, No, and Cancel buttons.

Because the dialog is modal, the user must answer it before interacting with the main window again.

Acting On The User's Choice

Once the dialog closes, MessageBoxW gives us a result code. We do not close the app blindly; instead, we check whether the user clicked Yes. Only then do we trigger the window destruction process.

C++
                    // Evaluate the user's response from the modal interaction
                    if (result == IDYES) {
                        // Only destroy the window if the user confirmed their intent
                        DestroyWindow(hwnd);
                    }
                    break;
                }
            }
            return 0;
        }

This is the safety check that changes the app flow. If the result is IDYES, DestroyWindow(hwnd) is called. If the result is anything else, such as clicking No, the function reaches break, then returns 0 for WM_COMMAND, and the app stays open.

A Note on Window Closing: This if check inside WM_COMMAND only handles the "Exit" menu item. If the user clicks the "X" button on the top-right of the window, Windows sends a WM_CLOSE message instead of a command message. We will implement confirmation for the "X" button in the upcoming practices.

Completing The Close Sequence

Even with a confirmation dialog added, we need to handle the final shutdown step properly. When the window is destroyed—either by our DestroyWindow call or the default system behavior—we must ensure the application exits its message loop by responding to WM_DESTROY.

C++
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
    }

    return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}

So, the app still shuts down cleanly; we have simply added a decision point in the menu before that shutdown begins.

Conclusion and Next Steps

In this lesson, we kept the menu structure from the previous unit, returned to WM_COMMAND, and upgraded the Exit path with a modal MessageBoxW confirmation. We also refined our window procedure to handle WM_CLOSE and WM_DESTROY as distinct steps.

This is a strong step forward because our program now behaves with more care and feels closer to a real Windows application. In the practice tasks ahead, we will reinforce this pattern so we can add confirmation logic with confidence.

Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal