Cómo convertirse en un ingeniero senior de Windows, luego comenzar desde el menú de programación

El proceso de creación de un menú en la aplicación de Windows es el siguiente:

1. Crea recursos de menú

2. Recurso del menú de carga de la aplicación

3. La aplicación responde a los mensajes de eventos del menú.

Primero distinga algunos conceptos:

<1> "Menú principal" y "Menú principal" tienen el mismo significado.

<2> Los elementos del menú principal se denominan "menú emergente" o "submenú".

<3> El elemento del menú emergente puede ser otro menú emergente.

<4> El estado del menú: habilitado, deshabilitado. Invalidación, la diferencia entre la invalidación y los dos anteriores es el texto de la pantalla gris.

1. Crea recursos de menú

Al crear recursos de menú, puede usar dos métodos: uno es usar el editor IDE para crear el menú; el otro es editar el archivo .rc manualmente. El primer método se usa en muchos libros de texto MFC. Estoy aquí Principalmente presenta métodos manuales para editar los recursos del menú, que ayudarán a todos a comprender los recursos de la programación IDE.

Si crea un recurso de menú en la secuencia de comandos de recurso * .rc, debe crear un archivo * .H correspondiente, que se utiliza para resolver el problema de referencia de símbolo del identificador de recurso.

Pero hay un accidente, el nombre del menú debe ser un símbolo y la cadena de nombre no se puede utilizar. La siguiente es la sintaxis básica de la descripción de MEMU que se encuentra comúnmente en archivos * .rc:

MENU_NAME MENU DISCARDABLE
{
       POPUP “name”            
       {
              MENUITEM  “name”, MENU_ID
}
}

MENU_NAME puede ser una cadena de nombre o un símbolo. La palabra clave DISCARDABLE está un poco desactualizada pero aún es necesaria. Las definiciones del menú de primer nivel en el menú comienzan todas con la palabra clave POPUP. Los elementos del menú están definidos por MENUITEM, como para MENU_ID es definido en el archivo * .h. El siguiente ejemplo:

// .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

Debe utilizar MAKEINTRESOURCE (MainMenu) o MAKEINTRESOURCE (100) para acceder a este recurso de menú.

Si desea configurar una tecla de acceso rápido o una tecla de acceso directo, puede usar el guión (&) para lograr esta función. Por ejemplo:

MENUITEM “E&xit”, MENU_FILE_ID_EXIT

Haga x una tecla de acceso rápido y

POPUP “&File”

Hacer de F una tecla de método abreviado utilizada por Alt + F

2. Cargar menú

En la definición de la clase de Windows, el código que define el menú es:

WNDCLASSEX wnd;
wnd.lpszMenuName = NULL;      //默认情况下

Simplemente asígnelo al nombre del menú:

wnd.lpszMenuName = “MainMenu”;

o

wnd.lpszMenuName = MAKEINTRESOURCE(MainMenu);

De esta manera, todas las ventanas creadas tendrán el mismo menú. Para resolver este problema, puede asignar un menú a una ventana pasando el identificador del menú durante el proceso de creación del menú. Cargue el recurso del menú a través de LoadMenu (), si tiene éxito, se devolverá un identificador HMENU.

LoadMenu()原型:
HMENU LoadMenu(HINSTANCE hInstance, // handle of applicationinstance
              LPCTSTRlpMenuName); // menu name string or menu-resource identifier

Cargue el menú "ManiMenu" en el parámetro del identificador del menú a través de la función estándar CreateWindow ():

// create the window
hwnd = CreateWindowEx(NULL, WINDOW_CLASS_NAME, “Sound”,
WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 400, 400, NULL,
LoadMenu(hinstance, “MainMenu”), hinstance, NULL);

La última forma de asociar el menú a la ventana es llamar a la función SetMenu ():

BOOL SetMenu( HWND hwnd, // handle of window to attach to
                     HMENUhMenu); // handle of menu

SetMenu () asocia directamente el menú a una ventana, este nuevo menú tendrá prioridad sobre cualquier menú asociado previamente. Por ejemplo:

// …
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);

Mensajes en respuesta a eventos del menú

El mensaje que pasa cuando suelta el mouse después de seleccionar un elemento del menú. Esto se refiere a un proceso de selección. El proceso de selección pasa un mensaje WM_COMMAND a la función WinProc de la ventana asociada con el menú. El ID del elemento de menú especificado y varios otros Los datos se almacena en el wparam y lparam del mensaje, como se muestra a continuación:

msg --- WM_COMMAND

LOWORD (lparam) ---- El identificador de la ventana que envió el mensaje

wparam --- ID del elemento de menú seleccionado

Posibles errores en la compilación:

DemoMenu.obj: error LNK2001: símbolo externo no resuelto__imp__PlaySoundA @ 12

Agregue winmm.lib al proyecto, proceso: Proyecto -> Configuración -> Conexión -> Agregar winmm.lib en las opciones del proyecto.

Acerca de la función de menú

La operación del menú no es más que agregar, eliminar, modificar y verificar cuatro operaciones desde la dirección general.

4.1 HMENUCreateMenu (VOID);

4.2 BOOL AppendMenu (HMENU hMenu, // manejar al menú

                         UINT uFlags, // opciones de elementos de menú

                         UINT_PTR uIDNewItem, // identificador, menú o submenú

                         LPCTSTR lpNewItem // contenido del elemento de menú);

4.3 BOOLInsertMenu (HMENU hMenu, // manejar al menú

                         UINT uPosition, // elemento al que precede el nuevo elemento

                         UINT uFlags, // opciones

                         UINT_PTR uIDNewItem, // identificador, menú o submenú

                         LPCTSTR lpNewItem // contenido del elemento de menú);

4.4 BOOLInsertMenuItem (HMENU hMenu, // manejar al menú

                UINT vital // identificador o posición

                BOOL fByPosition, // significado de uItem

                LPCMENUITEMINFO lpmii // información del elemento del menú);

Menú contextual

El menú del botón derecho no es diferente del menú normal. Justo cuando aparece. Necesito usar esta función

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);

El parámetro uFlags especifica la alineación del menú en el menú, haga clic con el botón izquierdo y haga clic con el botón derecho para seleccionar el elemento del menú

TPM_CENTERALIGN。TMP_LEFTALIGN。TMP_RIGHTALIGN

TPM_BOTTOMALIGN, TPM_TOPALIGN, TPM_VCENTERALIGN

TPM_LEFTBUTTPON, TPM_RIGHTBUTTON

TPM_NONOTIFY, TPM_RETURNCMD

Menu del sistema

Obtener el identificador del menú del sistema

HMENU GetSystemMenu ( 

         HWNDhWnd, // manejar a la ventana

       BOOL bRevert // opción de reinicio);

Cuando bRevert = FALSE. Dijo. Copie el menú del sistema y devuelva el controlador del menú de copia, este menú se puede cambiar. Cuando bRevert = TRUE, configure el menú del sistema en el estado original predeterminado. Y el valor de retorno de la función es NULL.

Acelerador

La tecla de aceleración también es un tipo de recurso, puede usar la tecla de método abreviado para abrir el elemento de comando rápidamente. Las teclas de aceleración se pueden agregar en los propios recursos o se pueden escribir directamente en el programa.

while(GetMessage(&msg,NULL,0,0))
{
if (!TranslateAccelerator(hWnd,hAccel,&msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

Aquí la función TranslateAccelerator traduce algunos mensajes de pulsación de teclas en mensajes WM_COMMAND o WM_SYSCOMMAND.

Ejemplo de demostración de código

La siguiente demostración es una demostración de menú que se basa completamente en el código y no se basa en la creación de recursos, incluida la barra de menú.

El menú contextual, el menú del sistema y las teclas de aceleración pueden cambiar y eliminar dinámicamente el menú. Únete a la operación.

#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;
}

El aprendizaje es, en última instancia, un proceso de aprendizaje y práctica y aplicación de lo aprendido. Por lo tanto, el autor ha creado una plataforma para que todos se comuniquen y aprendan. Durante el proceso de aprendizaje, puede encontrar varios problemas. Puede hacer preguntas en la plataforma. Hay expertos profesionales para responderle. Todos tienen años de programación. Experiencial , lo más importante es que poco a poco irás superando el miedo a las dificultades, ya no te preocupes por no poder entender o aprender, hay un mejor ambiente de aprendizaje y paquetes de regalo de aprendizaje gratuitos.

Supongo que te gusta

Origin blog.csdn.net/Python6886/article/details/111590985
Recomendado
Clasificación