メニューのソース定義
プログラムでメニューを作る
メニューをリソーススクリプトで表現し、それをアプリケーションで呼び出す方法は
これまでやってきたように、非常に簡素で効率的でした
しかし、他のプラットフォームのプログラマはこの方法を奇妙に思うかもしれません
こと Java プラットフォームではメニューをコンポーネントとして扱います
コンポーネントとは Windows のコントロールにあたる存在です
つまり、Java ではソース上でメニューを定義しそれを生成するのです
リソースによる定義は静的なメニューを生成しましたが
ソース上でメニューを定義し、生成することができればかなり動的なメニューを作れます
Win32 も、実はソース上でメニューを定義して生成することができるのです
メニューは CreateMenu() 関数で作ることができます
HMENU CreateMenu(VOID)
この関数に引数はありません
成功すれば空のメニューが生成されますが失敗すると NULL が返ります
しかし、この状態ではまだメニューは空の状態です
ここから、メニュー項目やサブメニューを追加していく必要があります
メニュー項目などを追加するには InsertMenuItem() 関数を使います
BOOL WINAPI InsertMenuItem(
HMENU hMenu , UINT uItem ,
BOOL fByPosition , LPMENUITEMINFO lpmii
);
hMenu には、追加するメニューのハンドル
uItem はメニュー項目を配置するID、またはインデックスを指定します
メニュー項目は、ここで指定された位置の前に配置されます
fByPosition が FALSE ならば uItem は ID であると判断され
それ以外であれば、インデックスであると判断されます
lpmii は MENUITEMINFO 構造体へのポインタです。このデータが、新しいメニューとなります
関数が成功すれば 0 以外、失敗すれば 0 が返ります
項目を追加する場合は MIIM_TYPE を指定して
dwTypeData メンバに、メニュー項目の文字列を格納します
項目がポップアップの場合は、さらに MIIM_SUBMENU を指定し
hSubMenu メンバにポップアップとなるサブメニューのハンドルを格納します
当然、サブメニューのハンドルも CreateMenu() 関数で生成できます
メニューIDは MIIM_ID を指定し wID メンバに値を指定します
#include <windows.h>
LRESULT CALLBACK WndProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) {
static HMENU hmenu , kitty;
MENUITEMINFO mii;
switch (msg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_CREATE:
hmenu = CreateMenu();
kitty = CreateMenu();
mii.cbSize = sizeof (MENUITEMINFO);
mii.fMask = MIIM_TYPE | MIIM_SUBMENU;
mii.fType = MFT_STRING;
mii.hSubMenu = kitty;
mii.dwTypeData = TEXT("Kitty on your lap");
InsertMenuItem(hmenu , 0 , TRUE , &mii);
mii.fMask = MIIM_TYPE;
mii.dwTypeData = TEXT("RENA");
InsertMenuItem(kitty , 0 , TRUE , &mii);
mii.dwTypeData = TEXT("YUKI");
InsertMenuItem(kitty , 1 , TRUE , &mii);
SetMenu(hwnd , hmenu);
return 0;
}
return DefWindowProc(hwnd , msg , wp , lp);
}
int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance ,
PSTR lpCmdLine , int nCmdShow ) {
HWND hwnd;
MSG msg;
WNDCLASS winc;
winc.style = CS_HREDRAW | CS_VREDRAW;
winc.lpfnWndProc = WndProc;
winc.cbClsExtra = winc.cbWndExtra = 0;
winc.hInstance = hInstance;
winc.hIcon = LoadIcon(NULL , IDI_APPLICATION);
winc.hCursor = LoadCursor(NULL , IDC_ARROW);
winc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
winc.lpszMenuName = NULL;
winc.lpszClassName = TEXT("KITTY");
if (!RegisterClass(&winc)) return -1;
hwnd = CreateWindow(
TEXT("KITTY") , TEXT("Kitty on your lap") ,
WS_OVERLAPPEDWINDOW | WS_VISIBLE ,
CW_USEDEFAULT , CW_USEDEFAULT ,
CW_USEDEFAULT , CW_USEDEFAULT ,
NULL , NULL ,
hInstance , NULL
);
if (hwnd == NULL) return -1;
while(GetMessage(&msg , NULL , 0 , 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
WM_CREATE メッセージの処理でメニューを定義しています
もちろん、この場合でも & プリフィックスによる Alt + 文字キーに対応しています
CreateMenu()
HMENU CreateMenu(VOID)
メニューを生成します
戻り値 - メニューのハンドル。失敗すれば NULL
InsertMenuItem()
BOOL WINAPI InsertMenuItem(
HMENU hMenu , UINT uItem ,
BOOL fByPosition , LPMENUITEMINFO lpmii
);
指定したメニューに新しい項目を追加します
hMenu - 対象のメニューハンドルを指定します
uItem - ID またはインデックスを指定します。この前に追加されます
fByPosition - FALSE なら uItem は ID、それ以外ならインデックスであると判断します
lpmii - 追加するメニューを表す MENUITEMINFO 構造体へのポインタを指定します
戻り値 - 成功すると 0 以外、失敗すると 0