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