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 submenus. Menu items can be enabled, disabled or greyed and checked or not checked.
Menus can either be constructed programmatically or built with a resource editor found in some IDEs. The CreateMenu(), AppendMenu() and InsertMenu() functions are the primary API function calls when building and maintaining menus at run time-
To create a menu use the CreateMenu() API function. The menu is initially empty. The prototype of this function is
HMENU CreateMenu();
If the function succeeds, the return value is a handle to the newly created menu. If the function fails, the return value is NULL.
To add items into the top-level menu, drop-down menu, submenu or context menu use the AppendMenu() API function. The prototype is-
BOOL AppendMenu(HMENU hMenu,UINT uFlags,UINT_PTR uIDNewItem,LPCSTR lpNewItem);
where
hMenu – A handle to the menu bar, drop-down menu, submenu, or shortcut menu to be changed.
uFlags -Controls the appearance and behaviour of the new menu item.
uIDNewItem – The identifier of the new menu item or, if the uFlags parameter is set to MF_POPUP, a handle to the drop-down menu or submenu.
lpNewItem -The content of the menu item. Can be one of the following: MF_BITMAP; MF_OWNERDRAW; MF_STRING
If the function succeeds, the return value is nonzero. If the function fails, the return value is zero.
For further detailed reading
https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-appendmenua
The ModifyMenu() function changes an existing menu item. The prototype of this function is
BOOL ModifyMenu(HMENU hMnu,UINT uPosition,UINT uFlags,UINT uIDNewItem,LPCTSTR lpNewItem);
hMnu – Handle to the menu to be changed.
uPosition – Specifies the menu item to be changed, as determined by the uFlags parameter.
uFlags – Specifies flags that control the interpretation of the uPosition parameter and the content, appearance, and behavior of the menu item.
uIDNewItem – Specifies either the identifier of the modified menu item or the handle to the drop-down menu or submenu.
lpNewItem – Pointer to the content of the changed menu item.
Returns nonzero if the function is successful; otherwise zero.
For further detailed reading
https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-modifymenua
To insert a new menu item at the specified position in a menu use the IntertMenuItem() API function. The prototype is
BOOL InsertMenuItem(HMENU hmenu,UINT item,BOOL fByPosition,LPCMENUITEMINFOA lpmi);
hMenu – Handle to the menu in which the new menu item is inserted.
uItem – Identifier or position of the menu item before which to insert the new item.
fByPosition – Value specifying the meaning of uItem. If this parameter is FALSE, uItem is a menu item identifier. Otherwise, it is a menu item position.
lpmii – Pointer to a MENUITEMINFO structure that contains information about the new menu item.
Returns nonzero if the function is successful; otherwise zero.
For further detailed reading.
https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-insertmenuitema
Deletes a menu item and the submenu associated with it, if any. The prototype of this function is
BOOL DeleteMenu(HMENU hMenu,UINT uPosition, UINT uFlags);
Where
hMenu– Handle to the menu to be changed.
uPosition – Specifies the menu item that is to be deleted
nFlags – Is used to interpret nPosition
Returns nonzero if the function is successful; otherwise zero.
WM_COMMAND – fires when the user selects an active menu item. The value of the LOWORD(wParam) contains the menu item selected.
WM_INITMENU – WM_INITMENU – fires whenever the user clicks anywhere in the menu bar but before the menu becomes active giving an application the opportunity to change the menu before an item is chosen. The wParam contains a handle to the menu to be initialised.
For further reading https://docs.microsoft.com/en-us/windows/win32/menurc/wm-initmenu
WM_MENUSELECT – generated when the user is hovering over a particular menu but before being selected. It does not fire for top-level menu items. The low-order word of wParam specifies the menu item or submenu index while the high-order word of wParam specifies one or more menu flags. The lparam contains a handle to the menu that was clicked.
For further reading https://docs.microsoft.com/en-us/windows/win32/menurc/wm-menuselect
WM_INITMENUPOPUP – Sent when a drop-down menu or submenu is about to become active. This allows an application to modify the menu before it is displayed. The wParam is handle to the drop-down menu or submenu. The low-order lParam word specifies the zero-based relative position of the menu item while the high-order word indicates whether the drop-down menu is the window menu. If the menu is the window menu, this parameter is TRUE; otherwise, it is FALSE.
For further reading https://docs.microsoft.com/en-us/windows/win32/menurc/wm-initmenupopup
Popup menu 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 TrackPopupMenu() function is used to display a context menu in a specific position of the screen. The popup menu can be loaded from an existing resource or can be created dynamically with a call to CreatePopupMenu().
The prototype for the TrackPopupMenu is –
BOOL TrackPopupMenu(HMENU hMenu,UINT uFlags,int x,int y,int nReserved,HWND hWnd,const RECT *prcRect);
Where
HMENU - A handle to the shortcut menu to be displayed
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.
PM_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
The code section below creates a window with a top-level menu, a single drop-down menu and two selectable menu items. In addition, the same menu options are available via a “right-click” context menu. Selecting either will produce a message beep.
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
#define IDM_MENUITEM1 1
#define IDM_MENUITEM2 2
#define IDM_FILE_QUIT 3
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,PWSTR lpCmdLine, int nCmdShow) {
MSG msg;
WNDCLASS wc = {0};
wc.lpszClassName = TEXT("Menu Demonstration");
wc.hInstance = hInstance;
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.lpfnWndProc = WndProc;
wc.hCursor = LoadCursor(0, IDC_ARROW);
RegisterClass(&wc);
CreateWindow(wc.lpszClassName, TEXT("Main and context menu"),WS_OVERLAPPEDWINDOW | WS_VISIBLE,100, 100, 350, 250, 0, 0, hInstance, 0);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch(msg) {
case WM_CREATE:
//Create handles for different types of menu
HMENU hMenubar;
HMENU hMenu;
//Create handles for context menu
HMENU hContextMenu;
POINT point;
//create empty menu
hMenubar = CreateMenu();
hMenu = CreateMenu();
//Create top level popup menu
AppendMenu(hMenubar, MF_POPUP, (UINT_PTR)hMenu,TEXT("&File"));
//Add menu items to pop up window
AppendMenu(hMenu, MF_STRING, IDM_MENUITEM1, TEXT("Item1"));
AppendMenu(hMenu, MF_STRING, IDM_MENUITEM2, TEXT("Item2"));
AppendMenu(hMenu, MF_SEPARATOR, 0, NULL);
AppendMenu(hMenu, MF_STRING, IDM_FILE_QUIT, TEXT("Quit"));
//Assigns a new menu to the specified window.
SetMenu(hwnd, hMenubar);
break;
//responds to main menu messages
case WM_COMMAND:
switch(LOWORD(wParam)) {
case IDM_MENUITEM1:
MessageBeep(MB_ICONINFORMATION);
break;
case IDM_MENUITEM2:
MessageBeep(MB_ICONWARNING);
break;
case IDM_FILE_QUIT:
SendMessage(hwnd, WM_CLOSE, 0, 0);
break;
}
break;
//The WM_INITMENU message is generated when the user clicks an item on the menu bar.
case WM_INITMENU:
{
HMENU selectedMenuID=(HMENU)wParam;//menu ID of selected menu item
}
break;
// WM_MENUSELECT is Sent to a menu's owner window when the user selects a menu item.
case WM_MENUSELECT:
{
UINT uItem = (UINT) LOWORD(wParam); // menu item or submenu index
UINT muFlags = (UINT) HIWORD(wParam); // menu flags
HMENU hmenu = (HMENU) lParam; // handle of menu clicked
}
// The WM_INITMENUPOPUP is sent when the user points to a menu item that opens a submenu
case WM_INITMENUPOPUP:
{
HMENU hMenuPopup = (HMENU) wParam; // handle of submenu
UINT uPos = (UINT) LOWORD(lParam); // submenu item position
BOOL bSystemMenu = (BOOL) HIWORD(lParam); // window menu flag
}
//responds to right mouse click by creating context menu
case WM_RBUTTONUP:
point.x = LOWORD(lParam);
point.y = HIWORD(lParam);
// Create context menu
hContextMenu = CreatePopupMenu();
//converts the client coordinates of a specified point to screen coordinates.
ClientToScreen(hwnd, &point);
//add menu iten to context menu
AppendMenu(hContextMenu, MF_STRING, IDM_MENUITEM1, TEXT("Option1"));
AppendMenu(hContextMenu, MF_STRING, IDM_MENUITEM2, TEXT("Option2"));
AppendMenu(hContextMenu, MF_SEPARATOR, 0, NULL);
AppendMenu(hContextMenu, MF_STRING, IDM_FILE_QUIT, TEXT("Quit"));
//Displays popup menu
TrackPopupMenu(hContextMenu, TPM_RIGHTBUTTON, point.x, point.y, 0, hwnd, NULL);
DestroyMenu(hContextMenu);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}