The process of creating a menu in Windows Application is as follows:
1. Create menu resources
2. Application load menu resource
3. The application responds to menu event messages
First distinguish a few concepts:
<1> "Main Menu" and "Top Menu" have the same meaning.
<2>The items in the main menu are called "pop-up menu" or "submenu".
<3> The item of the pop-up menu can be another pop-up menu.
<4>The status of the menu: enabled, disabled. Invalidation, the difference between invalidation and the previous two is the gray display text.
1. Create menu resources
When creating menu resources, you can use two methods: one is to use the IDE editor to create the menu; the other is to edit the .rc file manually. The first method is used in many MFC textbooks. I am here It mainly introduces manual methods to edit menu resources, which will help everyone understand the resources of using IDE programming.
If you create a menu resource in the *.rc resource script, you must create a *.H file corresponding to it, which is used to solve the symbol reference problem of the resource identifier.
But there is an accident, the menu name must be a symbol, and the name string cannot be used. The following is the basic syntax of MEMU description commonly found in *.rc files:
MENU_NAME MENU DISCARDABLE
{
POPUP “name”
{
MENUITEM “name”, MENU_ID
}
}
MENU_NAME can be a name string or a symbol. The keyword DISCARDABLE is a bit outdated but still necessary. The first-level menu definitions in the menu all start with the keyword POPUP. The menu items are defined by MENUITEM, as for MENU_ID It is defined in the *.h file. The following example:
// .RC资源文件中
MainMenu MENU DISCARDABLE
{
POPUP "File"
{
MENUITEM"Open", MENU_FILE_ID_OPEN
MENUITEM"Close", MENU_FILE_ID_CLOSE
MENUITEM"Save", MENU_FILE_ID_SAVE
MENUITEM"Exit", MENU_FILE_ID_EXIT
} // end popup
POPUP "Help"
{
MENUITEM"About", MENU_HELP_ABOUT
} // end popup
} // end top level menu
// .H文件中
// defines for the top level menu FILE
#define MENU_FILE_ID_OPEN 1000
#define MENU_FILE_ID_CLOSE 1001
#define MENU_FILE_ID_SAVE 1002
#define MENU_FILE_ID_EXIT 1003
// defines for the top level menu HELP
#define MENU_HELP_ABOUT 2000
在这里没有定义”MainMenu”, 这样可以通过字符串而不是ID来访问该菜单. 如果我向如下方式定义了该项的ID
#define MainMenu 100
Must use MAKEINTRESOURCE(MainMenu) or MAKEINTRESOURCE(100) to access this menu resource.
If you want to set a hot key or shortcut key, you can use the hyphen (&) to achieve this function. For example:
MENUITEM “E&xit”, MENU_FILE_ID_EXIT
Make x a hotkey, and
POPUP “&File”
Make F a shortcut key used by Alt+F
2. Load menu
In the definition of the windows class, the code that defines the menu is:
WNDCLASSEX wnd;
wnd.lpszMenuName = NULL; //默认情况下
Just assign it to the name of the menu:
wnd.lpszMenuName = “MainMenu”;
or
wnd.lpszMenuName = MAKEINTRESOURCE(MainMenu);
In this way, every window created will have the same menu. To solve this problem, you can assign a menu to a window by passing the menu handle during the menu creation process. Load the menu resource through LoadMenu(), if If successful, an HMENU handle will be returned.
LoadMenu()原型:
HMENU LoadMenu(HINSTANCE hInstance, // handle of applicationinstance
LPCTSTRlpMenuName); // menu name string or menu-resource identifier
Load the menu "ManiMenu" into the menu handle parameter through the standard CreateWindow() function:
// create the window
hwnd = CreateWindowEx(NULL, WINDOW_CLASS_NAME, “Sound”,
WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 400, 400, NULL,
LoadMenu(hinstance, “MainMenu”), hinstance, NULL);
The last way to associate the menu to the window is to call the SetMenu() function:
BOOL SetMenu( HWND hwnd, // handle of window to attach to
HMENUhMenu); // handle of menu
SetMenu() directly associates the menu to a window, this new menu will take precedence over any previously associated menus. For example:
// …
wnd.lpszMenuName = NULL;
// …
hwnd = CreateWindowEx(NULL, WINDOW_CLASS_NAME, “Sound”,
WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 400, 400, NULL,
NULL, // handle to menu ,note it’s null.
hinstance, NULL);
//…
// load the menu resource
HMENU hMenu = LoadMenu(hinstance, “MainMenu”);
// attach the menu to the window
SetMenu(hwnd, hMemu);
Messages in response to menu events
The message passing when you release the mouse after selecting a menu item. This refers to a selection process. The selection process passes a WM_COMMAND message to the WinProc function of the window associated with the menu. The specified menu item ID and various other The data is stored in the wparam and lparam of the message, as shown below:
msg --- WM_COMMAND
LOWORD(lparam) ---- The window handle that sent the message
wparam --- ID of the selected menu item
Possible errors in compilation:
DemoMenu.obj : error LNK2001: unresolved external symbol__imp__PlaySoundA@12
Add winmm.lib to the project, process: Project -> Settings -> Connection -> Add winmm.lib in the project options.
About Menu function
The operation of the menu is nothing more than adding, deleting, modifying and checking four operations from the general direction.
4.1 HMENUCreateMenu(VOID);
4.2 BOOL AppendMenu( HMENU hMenu, // handle to menu
UINT uFlags, //menu-item options
UINT_PTR uIDNewItem, // identifier, menu, or submenu
LPCTSTR lpNewItem //menu-item content);
4.3 BOOLInsertMenu( HMENU hMenu, // handle to menu
UINT uPosition, // item that new item precedes
UINT uFlags, // options
UINT_PTR uIDNewItem, // identifier, menu, or submenu
LPCTSTR lpNewItem // menu item content);
4.4 BOOLInsertMenuItem( HMENU hMenu, // handle to menu
UINT vital // identifier or position
BOOL fByPosition, // meaning of uItem
LPCMENUITEMINFO lpmii // menu item information);
Right click menu
The right-click menu is no different from the normal menu. Just when it pops up. Need to use this function
BOOLTrackPopupMenu( HMENU hMenu, // handle to shortcut menu
UINT uFlags, // options
int x, // horizontal position
int y, // vertical position
int nReserved, // reserved, must be zero
HWND hWnd, // handle to owner window
CONST RECT *prcRect // ignored);
The uFlags parameter specifies the alignment of the menu in the menu, left-click and right-click to select the menu item
TPM_CENTERALIGN。TMP_LEFTALIGN。TMP_RIGHTALIGN
TPM_BOTTOMALIGN, TPM_TOPALIGN, TPM_VCENTERALIGN
TPM_LEFTBUTTPON,TPM_RIGHTBUTTON
TPM_NONOTIFY, TPM_RETURNCMD
System menu
Get system menu handle
HMENU GetSystemMenu(
HWNDhWnd, // handle to window
BOOL bRevert // reset option);
When bRevert = FALSE. Said. Copy the menu of the system, and return the handle of the copy menu, this menu can be changed. When bRevert = TRUE, set the system menu to the default original state. And the function return value is NULL.
Accelerator
The accelerator key is also a kind of resource, it can use the shortcut key to open the command item quickly. Accelerator keys can be added in the resources themselves, or they can be written directly using programs.
while(GetMessage(&msg,NULL,0,0))
{
if (!TranslateAccelerator(hWnd,hAccel,&msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Here TranslateAccelerator function translates some key press messages into WM_COMMAND, or WM_SYSCOMMAND messages.
Code demonstration sample
The following demo is a menu demo that relies entirely on code and does not rely on creating resources, including the menu bar.
The right-click menu, system menu, and accelerator keys can dynamically change and delete the menu. Join operation.
#define OEMRESOURCE
# include<Windows.h>
#define IDM_FILE_OPEN 100
#define IDM_FILE_NEW 101
#define IDM_FILE_PIC 102
#define IDM_FILE_EXIT 103
#define IDM_MENU_ADD 104
#define IDM_MENU_REM 105
#define IDM_MENU_DEL 106
#define IDM_MENU_MOD 107
#define IDM_ABOUT 108
#define IDM_VERSION 109
#define IDM_MENU_NEW 110
#define IDM_POP_ONE 200
#define IDM_POP_TWO 201
#define IDM_SYS_ONE 300
#define IDM_SYS_TWO 301
LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
HMENU createOwnMenu(HWND hwnd);
HMENU createPopMenu(HWND hwnd);
HACCEL createAccelerator(HWND hwnd);
TCHAR* szAppName = TEXT("MenuClass");
TCHAR* szWndName = TEXT("ChangeMenu");
HACCEL hAccel = NULL;
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPreInstance,LPSTR lpCmdLine,int iCmdShow)
{
WNDCLASS wndCls;
HWND hWnd;
MSG msg;
wndCls.cbClsExtra = 0;
wndCls.cbWndExtra = 0;
wndCls.lpfnWndProc = WndProc;
wndCls.style = CS_HREDRAW | CS_VREDRAW;
wndCls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndCls.hCursor = LoadCursor(NULL,IDC_ARROW);
wndCls.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wndCls.hInstance = hInstance;
wndCls.lpszClassName = szAppName;
wndCls.lpszMenuName = NULL;
if(!RegisterClass(&wndCls))
{
MessageBox(NULL,TEXT("Register window failed"),TEXT("Error"),MB_OK);
}
hWnd = CreateWindow(szAppName,szWndName,WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
NULL,NULL,hInstance,NULL);
UpdateWindow(hWnd);
ShowWindow(hWnd,SW_NORMAL);
while(GetMessage(&msg,NULL,0,0))
{
if(!TranslateAccelerator(hWnd,hAccel,&msg))
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
static int nAdd = 1;
HMENU hMenu,hSonMenu,hTmpMenu;
HMENU hTrack,hSon;
HMENU hSysMenu;
POINT pt;
switch(msg)
{
case WM_CREATE:
hMenu = createOwnMenu(hwnd);
SetMenu(hwnd,hMenu);
hSysMenu = GetSystemMenu(hwnd,FALSE);
AppendMenu(hSysMenu,MF_SEPARATOR,0,NULL);
AppendMenu(hSysMenu,MF_STRING,IDM_SYS_ONE,TEXT("SysOne"));
AppendMenu(hSysMenu,MF_STRING,IDM_SYS_TWO,TEXT("SysTwo"));
hAccel = createAccelerator(hwnd);
break;
case WM_SYSCOMMAND:
switch(LOWORD(wParam))
{
case IDM_SYS_ONE:
MessageBox(NULL,TEXT("This is added system menu item1"),NULL,MB_OK);
break;
case IDM_SYS_TWO:
MessageBox(NULL,TEXT("This is added system menu item2"),NULL,MB_OK);
break;
}
break;
case WM_COMMAND:
hMenu = GetMenu(hwnd);
switch(LOWORD(wParam))
{
case IDM_FILE_OPEN:
MessageBox(NULL,TEXT("File Open selected"),TEXT("Test check"),MB_OK);
break;
case IDM_MENU_ADD:
hTmpMenu = GetSubMenu(hMenu,2);
AppendMenu(hTmpMenu,MF_STRING,IDM_MENU_NEW+nAdd,TEXT("New Item"));
nAdd++;
DrawMenuBar(hwnd);
break;
case IDM_MENU_REM:
hTmpMenu = GetSubMenu(hMenu,2);
if( nAdd >1 )
{
nAdd--;
RemoveMenu(hTmpMenu,IDM_MENU_NEW+nAdd,MF_BYCOMMAND);
}
// 当菜单项时弹出菜单的时候,只切断弹出菜单跟所属菜单的联系,但不销毁对象
/*GetSubMenu(hTmpMenu,2);
RemoveMenu(hTmpMenu,2,MF_BYPOSITION);*/
DrawMenuBar(hwnd);
break;
case IDM_MENU_MOD:
hTmpMenu = GetSubMenu(hMenu,2);
ModifyMenu(hTmpMenu,0,MF_BYPOSITION,IDM_ABOUT,TEXT("Modified Item"));
DrawMenuBar(hwnd);
break;
case IDM_MENU_DEL:
hTmpMenu = GetSubMenu(hMenu,2);
DeleteMenu(hTmpMenu,2,MF_BYPOSITION);
DrawMenuBar(hwnd);
break;
}
break;
case WM_RBUTTONDOWN:
hTrack = createPopMenu(hwnd);
hSon = GetSubMenu(hTrack,0);
pt.x = LOWORD(lParam);
pt.y = HIWORD(lParam);
ClientToScreen(hwnd,&pt);
TrackPopupMenu(hSon,TPM_LEFTBUTTON| TPM_RIGHTALIGN,pt.x,pt.y,0,hwnd,NULL);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd,msg,wParam,lParam);
}
HMENU createOwnMenu(HWND hwnd)
{
HMENU hMenu = CreateMenu();
HMENU hPopMenu = CreateMenu();
//MF_BYPOSIOTION,MF_BYCOMMAND is not useful here in AppendMenu
AppendMenu(hPopMenu,MF_STRING|MF_CHECKED|MF_GRAYED,IDM_FILE_OPEN,TEXT("&Open"));
InsertMenu(hPopMenu,0,MF_BYPOSITION|MF_STRING|MF_DISABLED,IDM_FILE_NEW,TEXT("&New"));
HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE);
HBITMAP hBmp = (HBITMAP)LoadImage(hInstance,TEXT("bitmap1.bmp"),IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
AppendMenu(hPopMenu,MF_BITMAP,IDM_FILE_PIC,(LPCWSTR)hBmp);
AppendMenu(hPopMenu,MF_SEPARATOR,NULL,NULL);
AppendMenu(hPopMenu,MF_STRING,IDM_FILE_EXIT,TEXT("&Exit"));
SetMenuItemBitmaps(hPopMenu,IDM_FILE_PIC,MF_BYCOMMAND,hBmp,hBmp);
AppendMenu(hMenu,MF_POPUP,(UINT_PTR)hPopMenu,TEXT("File"));
hPopMenu = CreateMenu();
AppendMenu(hPopMenu,MF_STRING,IDM_MENU_ADD,TEXT("&Add"));
AppendMenu(hPopMenu,MF_STRING,IDM_MENU_REM,TEXT("&Remove"));
AppendMenu(hPopMenu,MF_STRING,IDM_MENU_MOD,TEXT("&Modify"));
AppendMenu(hPopMenu,MF_STRING,IDM_MENU_DEL,TEXT("&Delete"));
AppendMenu(hMenu,MF_POPUP,(UINT_PTR)hPopMenu,TEXT("Menu"));
hPopMenu = CreateMenu();
AppendMenu(hPopMenu,MF_STRING,IDM_ABOUT,TEXT("About"));
AppendMenu(hPopMenu,MF_STRING,IDM_VERSION,TEXT("Version"));
HMENU hSonMenu = CreateMenu();
AppendMenu(hSonMenu,MF_STRING,IDM_MENU_NEW,TEXT("Son"));
AppendMenu(hPopMenu,MF_POPUP,(UINT_PTR)hSonMenu,TEXT("Son Menu"));
AppendMenu(hMenu,MF_POPUP,(UINT_PTR)hPopMenu,TEXT("Change"));
return hMenu;
}
HMENU createPopMenu(HWND hwnd)
{
HMENU hMenu = CreateMenu();
HMENU hPop = CreateMenu();
AppendMenu(hPop,MF_STRING,IDM_POP_ONE,TEXT("One"));
AppendMenu(hPop,MF_STRING,IDM_POP_TWO,TEXT("Twod"));
AppendMenu(hMenu,MF_POPUP,(UINT_PTR)hPop,TEXT("Pop"));
return hMenu;
}
HACCEL createAccelerator(HWND hwnd)
{
ACCEL acce[2];
acce[0].fVirt = FCONTROL | FNOINVERT | FVIRTKEY;
acce[0].key = 'A';
acce[0].cmd = IDM_MENU_ADD;
acce[1].fVirt = FCONTROL | FNOINVERT | FVIRTKEY;
acce[1].key = 'R';
acce[1].cmd = IDM_MENU_REM;
HACCEL hAccel = CreateAcceleratorTable(acce,2);
return hAccel;
}
Learning is, in the final analysis, a process of learning and practicing, and applying what has been learned. Therefore, the author has created a platform for everyone to communicate and learn. During the learning process, you may encounter various problems. You can ask questions on the platform. There are professional experts to answer you. They all have years of programming. Experientially, the most important thing is that you will gradually overcome the fear of difficulty, no longer worry about not being able to understand or learn, there is a better learning environment and free learning gift packages, etc.