Como se tornar um engenheiro sênior do Windows e, em seguida, começar a partir da programação do menu

O processo de criação de um menu no aplicativo do Windows é o seguinte:

1. Crie recursos de menu

2. Recurso do menu de carregamento do aplicativo

3. O aplicativo responde às mensagens de eventos do menu

Primeiro, diferencie alguns conceitos:

<1> "Menu principal" e "Menu superior" têm o mesmo significado.

<2> Os itens no menu principal são chamados de "menu pop-up" ou "submenu".

<3> O item do menu pop-up pode ser outro menu pop-up.

<4> O status do menu: ativado, desativado. Invalidação, a diferença entre a invalidação e as duas anteriores é o texto cinza do display.

1. Crie recursos de menu

Ao criar recursos de menu, você pode usar dois métodos: um é usar o editor IDE para criar o menu; o outro é editar o arquivo .rc manualmente. O primeiro método é usado em muitos livros didáticos do MFC. Estou aqui. métodos manuais para editar recursos de menu, que ajudarão todos a entender os recursos de uso da programação IDE.

Se você criar um recurso de menu no script de recurso * .rc, deverá criar um arquivo * .H correspondente a ele, que será usado para resolver o problema de referência de símbolo do identificador de recurso.

Mas há um acidente, o nome do menu deve ser um símbolo e a string do nome não pode ser usada. A seguir está a sintaxe básica da descrição MEMU comumente encontrada em arquivos * .rc:

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

MENU_NAME pode ser uma string de nome ou um símbolo. A palavra-chave DISCARDABLE está um pouco desatualizada, mas ainda é necessária. Todas as definições de menu de primeiro nível no menu começam com a palavra-chave POPUP. Os itens de menu são definidos por MENUITEM, assim como para MENU_ID. definido no arquivo * .h. O exemplo a seguir:

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

Deve-se usar MAKEINTRESOURCE (MainMenu) ou MAKEINTRESOURCE (100) para acessar este recurso de menu.

Se você deseja definir uma tecla de atalho ou tecla de atalho, pode usar o hífen (&) para realizar esta função. Por exemplo:

MENUITEM “E&xit”, MENU_FILE_ID_EXIT

Faça x uma tecla de atalho, e

POPUP “&File”

Faça de F uma tecla de atalho usada por Alt + F

2. Carregar menu

Na definição da classe windows, o código que define o menu é:

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

Basta atribuí-lo ao nome do menu:

wnd.lpszMenuName = “MainMenu”;

ou

wnd.lpszMenuName = MAKEINTRESOURCE(MainMenu);

Desta forma, todas as janelas criadas terão o mesmo menu. Para resolver este problema, você pode atribuir um menu a uma janela passando o identificador de menu durante o processo de criação do menu. Carregue o recurso de menu através de LoadMenu (), se for bem-sucedido, um identificador HMENU será retornado.

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

Carregue o menu "ManiMenu" no parâmetro de manipulação do menu por meio da função CreateWindow () padrão:

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

A última forma de associar o menu à janela é chamar a função SetMenu ():

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

SetMenu () associa diretamente o menu a uma janela, este novo menu terá precedência sobre quaisquer menus anteriormente associados.

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

Mensagens em resposta a eventos do menu

A mensagem que passa quando você libera o mouse após selecionar um item de menu. Refere-se a um processo de seleção. O processo de seleção passa uma mensagem WM_COMMAND para a função WinProc da janela associada ao menu. O ID do item de menu especificado e vários outros Os dados é armazenado no wparam e lparam da mensagem, conforme mostrado abaixo:

msg --- WM_COMMAND

LOWORD (lparam) ---- O identificador da janela que enviou a mensagem

wparam --- ID do item de menu selecionado

Possíveis erros na compilação:

DemoMenu.obj: erro LNK2001: símbolo externo não resolvido__imp__PlaySoundA @ 12

Adicione winmm.lib ao projeto, processe: Projeto -> Configurações -> Conexão -> Adicionar winmm.lib nas opções do projeto.

Sobre a função Menu

O funcionamento do menu nada mais é do que adicionar, excluir, modificar e verificar quatro operações na direção geral.

4.1 HMENUCreateMenu (VOID);

4.2 BOOL AppendMenu (HMENU hMenu, // manipular para o menu

                         UINT uFlags, // opções de item de menu

                         UINT_PTR uIDNewItem, // identificador, menu ou submenu

                         LPCTSTR lpNewItem // conteúdo do item de menu);

4.3 BOOLInsertMenu (HMENU hMenu, // lidar com o menu

                         UINT uPosition, // item que o novo item precede

                         UINT uFlags, // opções

                         UINT_PTR uIDNewItem, // identificador, menu ou submenu

                         LPCTSTR lpNewItem // conteúdo do item de menu);

4.4 BOOLInsertMenuItem (HMENU hMenu, // manipular para o menu

                UINT vital // identificador ou posição

                BOOL fByPosition, // significado de uItem

                LPCMENUITEMINFO lpmii // informações do item de menu);

Menu do botão direito

O menu do botão direito não é diferente do menu normal. Bem quando ele aparece. Precisa usar esta função

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

O parâmetro uFlags especifica o alinhamento do menu no menu, clique com o botão esquerdo e clique com o botão direito para selecionar o item de menu

TPM_CENTERALIGN。TMP_LEFTALIGN。TMP_RIGHTALIGN

TPM_BOTTOMALIGN, TPM_TOPALIGN, TPM_VCENTERALIGN

TPM_LEFTBUTTPON, TPM_RIGHTBUTTON

TPM_NONOTIFY, TPM_RETURNCMD

Menu do sistema

Obter identificador de menu do sistema

HMENU GetSystemMenu ( 

         HWNDhWnd, // manipula para a janela

       BOOL bRevert // opção de reset);

Quando bRevert = FALSE. Disse. Copie o menu do sistema, e volte a manivela do menu de cópia, este menu pode ser alterado. Quando bRevert = TRUE, defina o menu do sistema para o estado original padrão. E o valor de retorno da função é NULL.

Acelerador

A tecla aceleradora também é um tipo de recurso, ela pode usar a tecla de atalho para abrir o item de comando rapidamente. As chaves de aceleração podem ser adicionadas aos próprios recursos ou podem ser gravadas diretamente no programa.

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

Aqui, a função TranslateAccelerator traduz algumas mensagens de pressionamento de tecla em mensagens WM_COMMAND ou WM_SYSCOMMAND.

Amostra de demonstração de código

A demonstração a seguir é uma demonstração de menu que depende inteiramente de código e não depende da criação de recursos, incluindo a barra de menus.

O menu do botão direito, o menu do sistema e as teclas aceleradoras podem alterar e excluir dinamicamente o menu. Junte-se à operação.

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

Aprender é, em última análise, um processo de aprender e praticar e aplicar o que foi aprendido. Portanto, o autor criou uma plataforma para que todos se comuniquem e aprendam. Durante o processo de aprendizagem, você pode encontrar vários problemas. Você pode fazer perguntas na plataforma. Existem especialistas profissionais para responder. Todos eles têm anos de programação. Experiencialmente , o mais importante é que aos poucos você supere o medo das dificuldades, não se preocupe mais em não conseguir entender ou aprender, existe um ambiente de aprendizagem melhor e pacotes de brindes gratuitos de aprendizagem.

Acho que você gosta

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