A menubar is one of the most visible parts of the GUI application. It is a group of commands located in various menus. While in console applications you had to remember all those arcane commands, here we have most of the commands grouped into logical parts. There are accepted standards that further reduce the amount of time spending to learn a new application. A menu is a hierachical control. On the top, there is a menubar. A menubar contains a list of menus. Menus can contain either menu items or other menus calles submenus. A menu item that carries out a command is called a command item or a command. On Windows, menubar is sometimes called a toplevel menu, menus and submenus are called popup menus. Menu items are usually grouped into some logical groups. These groups are divided by a separator. It is a small veritcal line.
In the following example, we will create a menubar and three menu commands. We will also create a separator.
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void AddMenus(HWND);
#define IDM_FILE_NEW 1
#define IDM_FILE_OPEN 2
#define IDM_FILE_QUIT 3
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{
MSG msg ;
WNDCLASS wc = {0};
wc.lpszClassName = "Menu" ;
wc.hInstance = hInstance ;
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.lpfnWndProc = WndProc ;
wc.hCursor = LoadCursor(0, IDC_ARROW);
RegisterClass(&wc);
CreateWindow( wc.lpszClassName, "Menu",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
100, 100, 200, 150, 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:
AddMenus(hwnd);
break;
case WM_COMMAND:
switch(LOWORD(wParam)) {
case IDM_FILE_NEW:
case IDM_FILE_OPEN:
Beep(50, 100);
break;
case IDM_FILE_QUIT:
SendMessage(hwnd, WM_CLOSE, 0, 0);
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
void AddMenus(HWND hwnd) {
HMENU hMenubar;
HMENU hMenu;
hMenubar = CreateMenu();
hMenu = CreateMenu();
AppendMenu(hMenu, MF_STRING, IDM_FILE_NEW, "&New");
AppendMenu(hMenu, MF_STRING, IDM_FILE_OPEN, "&Open");
AppendMenu(hMenu, MF_SEPARATOR, 0, NULL);
AppendMenu(hMenu, MF_STRING, IDM_FILE_QUIT, "&Quit");
AppendMenu(hMenubar, MF_POPUP, (UINT_PTR)hMenu, "&File");
SetMenu(hwnd, hMenubar);
}
hMenubar = CreateMenu(); hMenu = CreateMenu();
Menubar and menus are all created using the CreateMenu() function call.
AppendMenu(hMenu, MF_STRING, IDM_FILE_NEW, "&New"); AppendMenu(hMenu, MF_STRING, IDM_FILE_OPEN, "&Open"); AppendMenu(hMenu, MF_SEPARATOR, 0, NULL); AppendMenu(hMenu, MF_STRING, IDM_FILE_QUIT, "&Quit"); AppendMenu(hMenubar, MF_POPUP, (UINT_PTR)hMenu, "&File");
Menu items and submenus are created using the AppendMenu() function call. What are we going to append, depends on the flag. MF_STRING appends a label, MF_SEPARATOR appends a separator and MF_POPUP appends a menu.
SetMenu(hwnd, hMenubar);
Finally, we set the menubar calling the SetMenu() function.
case WM_COMMAND:
switch(LOWORD(wParam)) {
case IDM_FILE_NEW:
case IDM_FILE_OPEN:
Beep(50, 100);
break;
case IDM_FILE_QUIT:
SendMessage(hwnd, WM_CLOSE, 0, 0);
break;
}
break;
If we select a menu item, the window procedure receives the WM_COMMAND message. The menu item id is in the low order word of the wParam value.
A popup menu is also called context menu. It is a list of commands that appears under some context. For example, in a Firefox web browser, when we right click on a web page, we get a context menu. Here we can reload a page, go back or view page source. If we right click on a toolbar, we get another context menu for managing toolbars.
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
#define IDM_FILE_NEW 1
#define IDM_FILE_OPEN 2
#define IDM_FILE_QUIT 3
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{
MSG msg ;
WNDCLASS wc = {0};
wc.lpszClassName = TEXT("Application");
wc.hInstance = hInstance;
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.lpfnWndProc = WndProc;
wc.hCursor = LoadCursor(0, IDC_ARROW);
RegisterClass(&wc);
CreateWindow( wc.lpszClassName, TEXT("Popup Menu"),
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
100, 100, 200, 150, 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 )
{
HMENU hMenu;
POINT point;
switch(msg)
{
case WM_COMMAND:
switch(LOWORD(wParam)) {
case IDM_FILE_NEW:
case IDM_FILE_OPEN:
Beep(50, 100);
break;
case IDM_FILE_QUIT:
SendMessage(hwnd, WM_CLOSE, 0, 0);
break;
}
break;
case WM_RBUTTONUP:
point.x = LOWORD(lParam);
point.y = HIWORD(lParam);
hMenu = CreatePopupMenu();
ClientToScreen(hwnd, &point);
AppendMenu(hMenu, MF_STRING, IDM_FILE_NEW, TEXT("&New"));
AppendMenu(hMenu, MF_STRING, IDM_FILE_OPEN, TEXT("&Open"));
AppendMenu(hMenu, MF_SEPARATOR, 0, NULL);
AppendMenu(hMenu, MF_STRING, IDM_FILE_QUIT, TEXT("&Quit"));
TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, point.x, point.y, 0, hwnd, NULL);
DestroyMenu(hMenu);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}