Windowsのシニアエンジニアになる方法、そしてメニュープログラミングから始める方法

Windowsアプリケーションでメニューを作成するプロセスは次のとおりです。

1.メニューリソースを作成します

2.アプリケーションロードメニューリソース

3.アプリケーションはメニューイベントメッセージに応答します

まず、いくつかの概念を区別します。

<1>「メインメニュー」と「トップメニュー」は同じ意味です。

<2>メインメニューの項目を「ポップアップメニュー」または「サブメニュー」と呼びます。

<3>ポップアップメニューの項目は、別のポップアップメニューにすることができます。

<4>メニューのステータス:有効、無効。無効化、無効化と前の2つの違いは、灰色の表示テキストです。

1.メニューリソースを作成します

メニューリソースを作成するときは、IDEエディタを使用してメニューを作成する方法と.rcファイルを手動で編集する方法の2つの方法を使用できます。最初の方法は多くのMFC教科書で使用されています。ここでは主に紹介しますメニューリソースを編集する手動の方法。これは、IDEプログラミングを使用するリソースを誰もが理解するのに役立ちます。

* .rcリソーススクリプトでメニューリソースを作成する場合は、それに対応する* .Hファイルを作成する必要があります。これは、リソース識別子のシンボル参照の問題を解決するために使用されます。

しかし、事故があり、メニュー名は記号でなければならず、名前文字列は使用できません。以下は、*。rcファイルで一般的に見られるMEMU記述の基本構文です。

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

MENU_NAMEは、名前の文字列または記号にすることができます。キーワードDISCARDABLEは少し古くなっていますが、それでも必要です。メニューの第1レベルのメニュー定義は、すべてキーワードPOPUPで始まります。メニュー項目は、MENU_IDと同様にMENUITEMによって定義されます。 * .hファイルで定義されています。次の例:

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

このメニューリソースにアクセスするには、MAKEINTRESOURCE(MainMenu)またはMAKEINTRESOURCE(100)を使用する必要があります。

ホットキーまたはショートカットキーを設定する場合は、ハイフン(&)を使用してこの機能を実行できます。次に例を示します。

MENUITEM “E&xit”, MENU_FILE_ID_EXIT

xをホットキーにして、

POPUP “&File”

FをAlt + Fで使用されるショートカットキーにします

2.ロードメニュー

Windowsクラスの定義では、メニューを定義するコードは次のとおりです。

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

メニューの名前に割り当てるだけです。

wnd.lpszMenuName = “MainMenu”;

または

wnd.lpszMenuName = MAKEINTRESOURCE(MainMenu);

このようにして、作成されたすべてのウィンドウに同じメニューが表示されます。この問題を解決するには、メニュー作成プロセス中にメニューハンドルを渡して、ウィンドウにメニューを割り当てることができます。成功した場合は、LoadMenu()を使用してメニューリソースをロードします。 HMENUハンドルが返されます。

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

標準のCreateWindow()関数を使用して、メニュー「ManiMenu」をメニューハンドルパラメータにロードします。

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

メニューをウィンドウに関連付ける最後の方法は、SetMenu()関数を呼び出すことです。

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

SetMenu()は、メニューをウィンドウに直接関連付けます。この新しいメニューは、以前に関連付けられたメニューよりも優先されます。次に例を示します。

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

メニューイベントに応じたメッセージ

メニュー項目選択後にマウスを離したときに渡されるメッセージ。これは選択プロセスを指します。選択プロセスは、WM_COMMANDメッセージをメニューに関連付けられたウィンドウのWinProc関数に渡します。指定されたメニュー項目IDおよびその他のさまざまなデータ以下に示すように、メッセージのwparamとlparamに格納されます。

msg --- WM_COMMAND

LOWORD(lparam)----メッセージを送信したウィンドウのハンドル

wparam ---選択したメニュー項目のID

コンパイルで発生する可能性のあるエラー:

DemoMenu.obj:エラーLNK2001:未解決の外部シンボル__imp__PlaySoundA @ 12

プロジェクトにwinmm.libを追加し、次の手順を実行します。プロジェクト->設定->接続->プロジェクトオプションにwinmm.libを追加します。

メニュー機能について

メニューの操作は、一般的な方向からの4つの操作の追加、削除、変更、およびチェックにすぎません。

4.1 HMENUCreateMenu(VOID);

4.2 BOOL AppendMenu(HMENU hMenu、//メニューへのハンドル

                         UINT uFlags、// menu-itemオプション

                         UINT_PTR uIDNewItem、//識別子、メニュー、またはサブメニュー

                         LPCTSTR lpNewItem //メニュー-アイテムコンテンツ);

4.3 BOOLInsertMenu(HMENU hMenu、//メニューへのハンドル

                         UINT uPosition、//新しいアイテムが先行するアイテム

                         UINT uFlags、//オプション

                         UINT_PTR uIDNewItem、//識別子、メニュー、またはサブメニュー

                         LPCTSTR lpNewItem //メニュー項目の内容);

4.4 BOOLInsertMenuItem(HMENU hMenu、//メニューへのハンドル

                UINTバイタル//識別子または位置

                BOOL fByPosition、// uItemの意味

                LPCMENUITEMINFO lpmii //メニュー項目情報);

右クリックメニュー

右クリックメニューは通常のメニューと同じです。ポップアップしたとき。この機能を使用する必要があります

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

uFlagsパラメーターは、メニュー内のメニューの配置を指定します。左クリックおよび右クリックしてメニュー項目を選択します。

TPM_CENTERALIGN。TMP_LEFTALIGN。TMP_RIGHTALIGN

TPM_BOTTOMALIGN、TPM_TOPALIGN、TPM_VCENTERALIGN

TPM_LEFTBUTTPON、TPM_RIGHTBUTTON

TPM_NONOTIFY、TPM_RETURNCMD

システムメニュー

システムメニューハンドルを取得する

HMENU GetSystemMenu( 

         HWNDhWnd、//ウィンドウへのハンドル

       BOOL bRevert //リセットオプション);

bRevert = FALSEの場合。前記。システムのメニューをコピーし、コピーメニューのハンドルを返すと、このメニューを変更できます。bRevert = TRUEの場合、システムメニューをデフォルトの元の状態に設定します。また、関数の戻り値はNULLです。

アクセル

アクセラレータキーも一種のリソースであり、ショートカットキーを使用してコマンド項目をすばやく開くことができます。アクセラレータキーは、リソース自体に追加することも、プログラムに直接書き込むこともできます。

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

ここで、TranslateAccelerator関数は、いくつかのキー押下メッセージをWM_COMMANDまたはWM_SYSCOMMANDメッセージに変換します。

コードデモンストレーションサンプル

次のデモは、完全にコードに依存し、メニューバーなどのリソースの作成に依存しないメニューデモです。

右クリックメニュー、システムメニュー、およびアクセラレータキーを使用して、メニューを動的に変更および削除できます。作戦に参加する。

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

学習とは、最終的な分析では、学習して実践し、学んだことを適用するプロセスです。そのため、著者は誰もがコミュニケーションと学習を行うためのプラットフォームを作成しました。学習プロセス中にさまざまな問題が発生する可能性があります。プラットフォームで質問をすることができます。専門家があなたに答えます。彼らはすべて長年のプログラミングを持っています。経験的に、最も重要なことは、困難の恐れを徐々に克服し、理解または学習できなくなることを心配する必要がなくなることです。より良い学習環境と無料の学習ギフトパッケージがあります。

おすすめ

転載: blog.csdn.net/Python6886/article/details/111590985