いままで、メニューバーのアイテムは、リソースファイルで定義していました。条件によってメニューを表示させたいときや、メニューをオーナードローしたいときは、CreateMenu()でメニューを作成する必要があります。
メニュー - インコのWindowsSDK で作成したソースを修正します。
流れ
関数: MyRegisterClass()
WNDCLASSEX構造体のlpszMenuNameメンバをNULLにします。
これにより、メニューバーが表示されなくなります。
リソースも、メニューに関する箇所を削除します。
WM_CREATE
1.CreateMenu()でメニューを作成
HMENU CreateMenu(VOID);
2.CreatePopupMenu()でドロップダウンメニュー、サブメニュー、ショートカットメニューのいずれかを作成。メニューは初期状態では空です。
HMENU CreatePopupMenu(VOID);
3.メニューアイテムの情報を定義するMENUITEMINFO構造体をセット。
先に構造体を初期化しておきます。
typedef struct tagMENUITEMINFO { UINT cbSize; // 構造体のサイズ UINT fMask; // 取得または設定するメンバ UINT fType; // アイテムのタイプ UINT fState; // アイテムの状態 UINT wID; // アイテムID HMENU hSubMenu; // サブメニューのハンドル HBITMAP hbmpChecked; // チェック表示時のビットマップ HBITMAP hbmpUnchecked; // チェック非表示時のビットマップ ULONG_PTR dwItemData; // 任意の32ビット値 LPTSTR dwTypeData; // アイテムの内容 UINT cch; // アイテムの文字列の長さ HBITMAP hbmpItem; // ビットマップハンドル } MENUITEMINFO, *LPMENUITEMINFO;
構造体メンバ | 定数と解説 | ||
---|---|---|---|
cbSize | 構造体のサイズ | ||
fMask | 有効にするメンバ | ||
MIIM_STATE | fStateが有効 | ||
MIIM_ID | wIDが有効 | ||
MIIM_SUBMENU | hSubMenuが有効 | ||
MIIM_CHECKMARKS | hbmpCheckedとhbmpUncheckedが有効 | ||
MIIM_DATA | dwItemDataが有効 | ||
MIIM_STRING | dwTypeDataが有効 | ||
MIIM_BITMAP | hbmpItemが有効 | ||
MIIM_FTYPE | fTypeが有効 | ||
fType | メニュー項目の種類・配置 | ||
MFT_OWNERDRAW | オーナードロー | ||
MFT_RADIOCHECK | チェックマークからラジオボタンにします。 ・hbmpCheckedメンバが0(NULL)のときのみ |
||
MFT_SEPARATOR | セパレーター | ||
fState | メニューアイテムの状態 | ||
MFS_ENABLED MFS_UNCHECKED MFS_UNHILITE |
通常表示 | ||
MFS_GLAYED MFS_DISABLED |
アイテムを灰色で表示し、選択不可にします。 | ||
MFS_CHECKED | アイテムにチェックマークをつけます。 | ||
MFS_HILITE | アイテムをハイライト表示 | ||
MFS_DEFAULT | デフォルトアイテムに設定 ・1つのメニューに対して1つまで ・太字で表示されます。 |
||
wID | メニューアイテムID | ||
hSubMenu | サブメニューまたはドロップダウンメニューのハンドル サブメニューを持たない場合は0(NULL) |
||
hbmpChecked |
アイテムがチェックされたときにアイテムの隣に表示するビットマップのハンドル 0(NULL):ラジオボタンまたは、チェックマーク。 ラジオボタンかチェックマークかは、fStateメンバで、MFT_RADIOCHECKを指定するかどうかで切り替え。 |
||
hbmpUnchecked | アイテムがチェックされていないときにアイテムの隣に表示するビットマップのハンドル 0(NULL):表示なし |
||
dwItemData | アイテムに関連付けられたアプリケーション定義の32ビット値 | ||
dwTypeData | メニューアイテムの内容 | ||
cch | アイテムのテキストを格納するバッファのサイズ | ||
hbmpItem | ビットマップのハンドル |
4.InsertMenuItem()で、メニューの項目を追加。
BOOL InsertMenuItem( HMENU hMenu, // メニューのハンドル UINT uItem, // メニュー項目または位置を指定 BOOL fByPosition, // uItemの種別 LPCMENUITEMINFO lpmii // MENUITEMINFO構造体へのポインタ );
hMenu | メニューのハンドル |
uItem | メニュー項目または位置を指定 この項目の前に新しい項目が挿入されます |
fByPosition |
uItemの種別 TRUE : uItemは位置 FALSE : uItemはメニュー項目のID |
lpmii | MENUITEMINFO構造体へのポインタ |
5.SetMenu()で、新しいメニューを指定されたウィンドウに割り当てます。
BOOL SetMenu( HWND hWnd, // ウィンドウハンドル HMENU hMenu // メニューハンドル );
ソースコードの入力
ソースコードは下記のように入れてください。
test.cpp
#include <windows.h> #include "resource.h" // グローバル変数: HMENU hMenu; // メニューのハンドル HMENU hSubMenu1; // メニューのハンドル HMENU hSubMenu2; // メニューのハンドル // このコード モジュールに含まれる関数の宣言を転送します: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MSG msg; MyRegisterClass(hInstance); // アプリケーションの初期化を実行します: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } // メイン メッセージ ループ: while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; } // // 関数: MyRegisterClass() // // 目的: ウィンドウ クラスを登録します。 // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(NULL , IDI_APPLICATION); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = NULL; wcex.lpszClassName = TEXT("HP"); wcex.hIconSm = LoadIcon(NULL , IDI_APPLICATION); return RegisterClassEx(&wcex); } // // 関数: InitInstance(HINSTANCE, int) // // 目的: メイン ウィンドウを作成します。 // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hWnd = CreateWindow(TEXT("HP"), TEXT("HP"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // // 関数: WndProc(HWND, UINT, WPARAM, LPARAM) // // 目的: メイン ウィンドウのメッセージを処理します。 // // WM_CREATE - ウインドウ作成時の処理 // WM_COMMAND - アプリケーション メニューの処理 // WM_DESTROY - 中止メッセージを表示して戻る // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; MENUITEMINFO mi; switch (message) { case WM_CREATE: hMenu = CreateMenu(); hSubMenu1 = CreatePopupMenu(); hSubMenu2 = CreatePopupMenu(); memset(&mi, 0, sizeof(MENUITEMINFO)); mi.cbSize = sizeof(MENUITEMINFO); mi.fMask = MIIM_TYPE | MIIM_SUBMENU; mi.fType = MFT_STRING; mi.fState = MFS_ENABLED; mi.wID = 0; mi.hSubMenu = hSubMenu1; mi.dwTypeData = TEXT("ファイル(&F)"); InsertMenuItem(hMenu, 0, TRUE, &mi); mi.wID = 1; mi.hSubMenu = hSubMenu2; mi.dwTypeData = TEXT("ヘルプ(&H)"); InsertMenuItem(hMenu, 1, TRUE, &mi); // サブメニュー mi.fMask = MIIM_TYPE | MIIM_ID; mi.fType = MFT_STRING; mi.wID = IDM_EXIT; mi.dwTypeData = TEXT("アプリケーションの終了(&X)"); InsertMenuItem(hSubMenu1, 0, TRUE, &mi); mi.wID = IDM_ABOUT; mi.dwTypeData = TEXT("バージョン情報(&A)..."); InsertMenuItem(hSubMenu2, 0, TRUE, &mi); SetMenu(hWnd, hMenu); break; case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // 選択されたメニューの解析: switch (wmId) { case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
上記の太線で示している箇所のみ追加です。
resource.h (変更なし)
#define IDM_ABOUT 104 #define IDM_EXIT 105 #define IDC_HP 109
test.rc リソースファイル
リソースファイルは中身を削除しました。