1. About System Menu
The System Menu appears when you click the top left corner of the window. In this short article, we will add our own command to the System Menu of the dialog box. You can do the same for SDI and MDI Applications. The windows notepad application below shows such System Menu:
In this Example, we will add our system menu item to the dialog-based application of Microsoft Foundation Class (MFC) Framework. After adding the Menu Item, we will also handle the mouse left click event for that Menu Item.
2. Customize System Menu Using GetSystemMenu
First, we create a Dialog-based MFC Application. We name this Application as “SysCommand” while we create it. Then, we add a command identifier in the resource.h file. We will link this identifier to our custom System Menu Item which we will create in the next section. The code snippet for the ID is shown below:
//Sample 01: Add the Command Identifier
#define IDM_SYSCOMMAND_CUSTOM 32771
The Application Wizard set up a class called CSysCommand if you used the same suggested project name while creating Application. We have to find the OnInitDialog function in it because we will invoke the System Menu here and add our Custom Menu Item to it. In the OnInitDialog, we make a call to CWnd member function GetSystemMenu to get the CMenu pointer pointing to the System Menu of our dialog.
Once we have the Menu returned by the GetSystemMenu , we add a Menu Item to it using AppendMenu function of the CMenu. We name this Menu Item as “Custom Menu”. After that, we supply the Command Identifier which we created in the previous section to it. The below code shows how we used the GetSystemMenu API:
//Sample 02: Get System Menu and
//Add your own menu item
CMenu * pSystemMenu = GetSystemMenu(FALSE);
The CMenu Class has a member function called AppendMenu and we can use it to add a menu item to the Menu. The first parameter specifies a flag useful for specifying extra styles for a Menu Item. Some crucial flags are below:
- MF_CHECKED tells the MFC to set a default check mark next to the item.
- MF_UNCHECKED tells the MFC to remove the default check mark.
- MF_ENABLED makes the Menu Item responds to the user interaction
- MF_GRAYED keeps the Menu item in disabled state.
- MF_SEPARATOR adds a separator line. When we specify this flag, other parameters to the AppendMenu can be ignored.
The second parameter passed to the Append Menu is a command identifier. We can use it to handle the click event raised by the Menu Item. The final argument sent to the Append Menu is a string, and it gets shown in the Menu. in our example, the display string of Menu Item is Custom Menu.
3. The OnSysCommand Handler
When a Menu Item is clicked from the Control Menu which is also called as System Menu, MFC sends WM_SYSCOMMAND to the parent of the Menu. In our case, the dialog is the parent, and it already responds to the default “About” Menu Item of the System Menu. So, we need to trace down to the code which displays the about dialog for our MFC dialog-based Application.
In the dialog class’s implementation file (.cpp), search for the function OnSysCommand. This function is the handler for all the System Menu commands. To know the Command Source, we compare the nID parameter with the Command Identifier and once the ID matches the dialog handles the Command. In our example, we check this nID parameter with Command Identifier for our Custom Menu Item and when a match occurs; we display a message box to the user. Below is the code:
void CSysCommandDlg::OnSysCommand(UINT nID, LPARAM lParam)
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
//Sample 03: Check nID with your Resource
//Identifier for the custom menu command.
else if(nID == IDM_SYSCOMMAND_CUSTOM)
_T("Your Custom System Command Invoked...")
In the above code snippet, we can see how the Menu Item “About …” is handled which runs from line number 3 to line number 7. We introduce an else if block to check the System Command target is IDM_SYSCOMMAND_CUSTOM. Remember, this is the command identifier linked to menu “Custom Menu”. Our handling code run from line number 8 to line number 15 of OnSysCommand handler.
4. Running the Example
Below given video shows the sample in action: