How to become a Windows senior engineer, then start from the menu programming

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.

Guess you like

Origin blog.csdn.net/Python6886/article/details/111590985