Welcome to Application Menus and Dialogs. In this lesson, we will create a menu bar, add a File menu, and make each menu choice trigger the right action.
This matters because menus are one of the main ways users interact with Windows applications. By the end of the lesson, we will not only place commands on the screen but also route those commands through the window procedure so that the program responds in a clean, organized way.
Before we write code, it helps to build a mental model. In WinAPI, a menu is not something we draw by hand. We create menu objects, attach them to a window, and then respond when Windows tells us a command was chosen.
The flow in this lesson is simple:
WM_CREATE: build the menu bar and its dropdown menu when the window is being created.WM_COMMAND: detect which menu item was clicked.WM_DESTROY: finish the application when the window is closing.
This message-based style is a major concept in WinAPI. We perform the setup once and then react to messages as the user interacts with the app.
Inside the window procedure implementation, we begin by defining IDs for the menu items. These IDs are the link between what the user clicks and the code that runs later. We also open the callback function that receives window messages.
The two constants act like stable labels for our commands. When Open is selected, Windows sends its ID; when Exit is selected, it sends a different one. The callback signature is also worth noticing: hwnd identifies the window, uMsg tells us which message arrived, and wParam plus lParam carry extra data.
We will use uMsg first to choose the message type, then use wParam to find the exact menu command.
Now we start handling messages. The best place to build a menu is WM_CREATE, because this message arrives as the window is being set up. Here, we create two menu handles: one for the top menu bar, and one for the File dropdown that lives under it.
HMENU is the WinAPI handle type for menus. We need two handles because the menu bar and the dropdown are separate objects. CreateMenu() makes the horizontal bar that sits at the top of the window. CreatePopupMenu() makes a submenu, which is exactly what the File menu is. This separation gives us the hierarchy we want: one bar, then items inside its dropdown.
With the dropdown created, we can fill it with commands. This is where the menu becomes useful to the user. We add an Open item, a separator line for visual grouping, and an Exit item.
AppendMenuW adds each entry to the submenu. MF_STRING means a normal clickable text command, while MF_SEPARATOR inserts a dividing line. The L before each string marks it as a wide string, which matches the Unicode W versions of WinAPI functions.
The & character is also important: it marks the keyboard access key, so &File supports Alt+F, and &Open... helps the user navigate by keyboard.
At this point, the File submenu exists, but it is still floating on its own. Next, we connect that submenu to the top-level menu bar and then assign the full menu bar to the window itself.
This call to AppendMenuW looks a little different because of MF_POPUP. In this case, the third argument is not a command ID but rather the submenu handle; therefore, we cast hFileMenu to UINT_PTR. The label L"&File" becomes the visible menu title on the bar. Then SetMenu(hwnd, hMenuBar) makes the menu appear on the window. Finally, return 0 tells Windows that we handled WM_CREATE ourselves.
Once the menu is visible, user clicks will arrive as WM_COMMAND. This is where the command IDs we defined earlier become useful. We inspect the low word of wParam, then choose the matching action.
WM_COMMAND can be used by menus and some controls, so LOWORD(wParam) is the key step that extracts the command ID. From there, the logic is straightforward:
ID_FILE_OPEN: show a message box for now, which proves the command path works.ID_FILE_EXIT: callDestroyWindow(hwnd)to begin closing the window.
This structure scales well. As the app grows, we can add more IDs and more case blocks without changing the overall pattern.
In this lesson, we built a full menu flow in small steps: we defined command IDs, created a menu bar and a popup menu, added menu items, attached the menu to the window, and routed user selections through WM_COMMAND.
That is a strong start for Application Menus and Dialogs, because we already have a window that behaves more like a real application. In the upcoming practice tasks, we will turn this understanding into hands-on code so that the menu logic becomes something we can write with confidence.
