In windows, a menu bar is a horizontal bar most often displayed immediately below the caption bar and usually containing a list of drop-down menu items. These drop-down menus can contain either other menu items or nested sub menus.
MFC encapsulates menus and all associated actions in the CMenu class. MFC menus are usually created programmatically or from a resource file which can then be loaded into the application at run time.
To create and maintain menus programmatically, the developer will need to instantiate on object of the class CMenu and then use the following member functions: CreateMenu(), CreatePopupMenu(), and AppendMenu() to create the menu items.
CreateMenu
Is used to create a top-level menu. The prototype of this function is
BOOL CreateMenu( );
Returns nonzero if the menu creation was successful. 0 if menu creation failed
CreatePopupMenu
Creates a pop-up menu and attaches it to the CMenu object. The prototype of this function is
BOOL CreatePopupMenu( );
Return Nonzero if the pop-up menu was successfully created; 0 if menu creation failed
AppendMenu
Appends a new item to the end of a menu. The prototype of this function is
BOOL AppendMenu( UINT nFlags, UINT nIDNewItem = 0, LPCTSTR lpszNewItem = NULL); BOOL AppendMenu( UINT nFlags, UINT nIDNewItem, const CBitmap* pBmp );
nFlags – Specifies information about the state of the new menu item.
nIDNewItem – Specifies either the command ID of the new menu item or, if nFlags is set to MF_POPUP, the menu handle ( HMENU) of a pop-up menu.
lpszNewItem – Specifies the content of the new menu item.
pBmp – Points to a CBitmap object that will be used as the menu item.
For more details reading
https://docs.microsoft.com/en-us/cpp/mfc/reference/cmenu-class?view=vs-2019#appendmenu
The ON_COMMAND macro
The ON_COMMAND macro in the message map links menu messages to a message response function. The prototype for this function is
ON_COMMAND( Id, mFuction )
where
id – is the menu items ID,
mFuction -is the name of the function that will handle that message.
To map a range of menu commands to a single message response use the ON_COMMAND_RANGE macro. The prototype for this macro is
ON_COMMAND_RANGE( id1, id2, mFunction )
where
id1 – Command ID at the beginning of a contiguous range of command IDs.
id2 – Command ID at the end of a contiguous range of command IDs.
mFunction – The name of the message-handler function to which the commands are mapped.
In order for this type of message mapping to work, the command IDs in the range must be consecutive.
Modifying Menus Programmatically
In addition to creating menus dynamically, menus can all be modified dynamically. The following table lists the CMenu member functions used to add, modify, and delete menu items.
InsertMenu
Inserts an item into a menu at a specified location. The prototype for this function is
BOOL InsertMenu( nPosition, nFlags, nIDNewItem, lpszNewItem ); BOOL InsertMenu( nPosition, nFlags, nIDNewItem, * pBmp );
where
nPosition – Specifies the menu item before which the new menu item is to be inserted.
nFlags – Specifie information about the state of the new menu item
nIDNewItem – Specifies either the command ID of the new menu item or, if nFlags is set to MF_POPUP, the menu handle (HMENU) of the pop-up menu.
lpszNewItem – Specifies the content of the new menu item.
pBmp – Points to a CBitmap object that will be used as the menu item.
Returns nonzero if the function is successful; otherwise 0.
For further reading
https://docs.microsoft.com/en-us/cpp/mfc/reference/cmenu-class?view=vs-2019#insertmenu
ModifyMenu
Changes the command ID, text, or other characteristics of a menu item.
BOOL ModifyMenu( nPosition, nFlags, nIDNewItem, lpszNewItem ); BOOL ModifyMenu( nPosition, nFlags, nIDNewItem, pBmp );
NPosition – Specifies the menu item to be changed.
nFlags, nIDNewItem, lpszNewItem-see insert menu
For further reading
https://docs.microsoft.com/en-us/cpp/mfc/reference/cmenu-class?view=vs-2019#modifymenu
DeleteMenu
Deletes a menu item and the submenu associated with it, if any. The prototype of this function is
BOOL DeleteMenu( UINT nPosition, UINT nFlags );
Where
nPosition – Specifies the menu item that is to be deleted
nFlags – Is used to interpret nPosition
Return nonzero if the function is successful; otherwise 0
For further reading
https://docs.microsoft.com/en-us/cpp/mfc/reference/cmenu-class?view=vs-2019#deletemenu
RemoveMenu
Deletes a menu item
BOOL RemoveMenu( UINT nPosition, UINT nFlags );
where
nPosition – Specifies the menu item to be removed.
nFlags – Specifies how nPosition is interpreted
Return nonzero if the function is successful; otherwise 0.
The difference between RemoveMenu and DeleteMenu is that if the item being removed has a submenu, then deleteMenu will remove the item and destroys the submenu, too. RemoveMenu removes the item but leaves the submenu extant in memory.
Before a menu is modified, the developer will need the CMenu pointer referencing the menu. MFC’s CWnd::GetMenu function returns a CMenu pointer for a window’s top-level menu or NULL if the window doesn’t have a top-level menu-
CMenu* pMenu = GetMenu (); pMenu->DeleteMenu (1, MF_BYPOSITION);
The Popup or Context Menu
Popup or context menus are those which generally appear when the user right-clicks. This menu is often referred to as a context menu because the options in the menu often relate to what was right-clicked. The popup menu can be loaded from an existing resource or can be created dynamically with a call to the function CreatePopupMenu().
The cmenu member function TrackPopupMenu() displays a context menu. The function prototype is
BOOL TrackPopupMenu (UINT nFlags, int x, int y, CWnd* pWnd, LPCRECT lpRect = NULL);
Where
nFlags – Specifies screen-position and mouse-position flags.
Use one of the following flags to specify how the function positions the shortcut menu horizontally.
TPM_CENTERALIGN – Centers the shortcut menu horizontally relative to the coordinate specified by the x parameter.
TPM_LEFTALIGN – Positions the shortcut menu so that its left side is aligned with the coordinate specified by the x parameter.
TPM_RIGHTALIGN – Positions the shortcut menu so that its right side is aligned with the coordinate specified by the x parameter.
Use one of the following flags to specify how the function positions the shortcut menu vertically.
TPM_BOTTOMALIGN – Positions the shortcut menu so that its bottom side is aligned with the coordinate specified by the y parameter.
TPM_TOPALIGN – Positions the shortcut menu so that its top side is aligned with the coordinate specified by the y parameter.
TPM_VCENTERALIGN – Centers the shortcut menu vertically relative to the coordinate specified by the y parameter.
x – Specifies the horizontal position in screen coordinates of the pop-up menu.
y – Specifies the vertical position in screen coordinates of the top of the menu on the screen.
pWnd – Identifies the window that owns the pop-up menu.
lpRect – Ignored.
Returns the result of calling TrackPopupMenu
Example
The short program below demonstrates a simple menu structure. Clicking file>new will produce a messagebox and file>exit will close the application. A right-click will produce a context menu containing the same menu items as the main menu
#include <afxwin.h> #define ID_NEW 2002 #define ID_EXIT 2004 #define IDM_MENUITEM1 2005 class CSimpleApp : public CWinApp { public: BOOL InitInstance(); }; class CMainFrame : public CFrameWnd { public: CMainFrame(); void OnFileNew(); void OnExit(); afx_msg void OnRButtonDown( UINT, CPoint ); DECLARE_MESSAGE_MAP() }; BOOL CSimpleApp::InitInstance(){ m_pMainWnd = new CMainFrame(); m_pMainWnd->ShowWindow(m_nCmdShow); return TRUE; } CMainFrame::CMainFrame() { Create(NULL, "MFC Menu Example"); //Create main menu CMenu *menu = new CMenu(); menu->CreateMenu(); //creare 2 submenu's CMenu *subMenu1 = new CMenu(); CMenu *subMenu2 = new CMenu(); //make submenu popup subMenu1->CreatePopupMenu(); subMenu2->CreatePopupMenu(); //append items to submenu menu->AppendMenu(MF_POPUP|MF_STRING, (UINT)subMenu1->m_hMenu, TEXT("File") ); menu->AppendMenu(MF_POPUP|MF_STRING, (UINT)subMenu2->m_hMenu, TEXT("Help") ); subMenu1->AppendMenu(MF_STRING, ID_NEW, TEXT("New")); subMenu1->AppendMenu(MF_STRING, ID_EXIT, TEXT("Exit")); SetMenu(menu); } BEGIN_MESSAGE_MAP(CMainFrame,CFrameWnd) ON_COMMAND(ID_NEW ,OnFileNew) ON_COMMAND(ID_EXIT ,OnExit) ON_WM_RBUTTONDOWN() ON_WM_RBUTTONUP() END_MESSAGE_MAP() CSimpleApp MFCApp1; //respond to menu selection new by creating message box afx_msg void CMainFrame::OnFileNew() { MessageBox(TEXT("New button clicked"),TEXT("menu demo"),MB_OK); } afx_msg void CMainFrame::OnExit() { PostMessage(WM_CLOSE,0,0); } //display context menu afx_msg void CMainFrame::OnRButtonDown(UINT nFlags, CPoint point) { CMenu *contextmenu; contextmenu = new CMenu(); contextmenu->CreatePopupMenu();//= CreatePopupMenu(); contextmenu->AppendMenu(MF_STRING,ID_NEW, TEXT("New")); contextmenu->AppendMenu(MF_STRING,ID_EXIT, TEXT("Exit")); ClientToScreen(&point); contextmenu->TrackPopupMenu(TPM_RIGHTBUTTON,point.x,point.y, this, NULL); }