メニューアイテムの設定

メニューの各項目は様々な設定が可能です。
例えば項目に表示される文字列や画像、チェックマークのオン/オフや無効状態といったものです。

SetMenuItemInfo関数

メニュー項目を設定するにはSetMenuItemInfo関数を使用します。

BOOL SetMenuItemInfoW(
 HMENU hmenu,
 UINT item,
 BOOL fByPositon,
 LPCMENUITEMINFOW lpmii
);
メニューハンドルhmenuのメニュー項目itemの情報をlpmiiに設定する。
成功した場合は0以外を、失敗した場合は0を返す。

hmenuはメニューハンドルです。

itemはメニュー項目を指定するための値ですが、これは次の引数fByPositonの値によって意味が変わります。
fByPositonFALSE(0)の場合、itemはメニュー項目の識別子を意味します。
TRUE(0以外)の場合は先頭からのインデックス(番号)を意味します。

lpmiiMENUITEMINFO構造体へのポインタです。

GetMenuItemInfo関数

メニュー項目の設定を取得するにはGetMenuItemInfo関数を使用します。

BOOL GetMenuItemInfoW(
 HMENU hmenu,
 UINT item,
 BOOL fByPosition,
 LPMENUITEMINFOW lpmii
);
メニューハンドルhmenuのメニュー項目itemの情報をlpmiiに格納する。
成功した場合は0以外を、失敗した場合は0を返す。

引数の意味はSetMenuItemInfo関数と同じです。

MENUITEMINFO構造体はメニュー項目の情報を格納する構造体です。

typedef struct tagMENUITEMINFOW {
 UINT cbSize;
 UINT fMask;
 UINT fType;
 UINT fState;
 UINT wID;
 HMENU hSubMenu;
 HBITMAP hbmpChecked;
 HBITMAP hbmpUnchecked;
 ULONG_PTR dwItemData;
 LPWSTR dwTypeData;
 UINT cch;
 HBITMAP hbmpItem;
} MENUITEMINFOW, *LPMENUITEMINFOW;
メニュー項目の情報を格納する構造体。

cbSizeメンバはこの構造体のサイズです。
つまりsizeof(MENUITEMINFO)を指定します。

fMaskメンバは取得または設定するメンバを指定します。
MENUITEMINFO構造体は多くの状態を一度に取得/設定可能ですが、毎回全ての設定を読み書きする必要はなく、この設定で必要な情報だけを取得/設定できます。
(ここで設定しなかったメンバは無視される)
以下の定数のいずれか、あるいは組み合わせを指定します。

定数 説明
MIIM_FTYPE fTypeメンバの取得/設定
MIIM_STATE fStateメンバの取得/設定
MIIM_ID wIDメンバの取得/設定
MIIM_SUBMENU hSubMenuメンバの取得/設定
MIIM_CHECKMARKS hbmpCheckedhbmpUncheckedメンバの取得/設定
MIIM_DATA dwItemDataメンバの取得/設定
MIIM_STRING dwTypeDataメンバの取得/設定
MIIM_BITMAP hbmpItemメンバの取得/設定
MIIM_TYPE fTypedwTypeDataメンバの取得/設定
MIIM_FTYPEと紛らわしいので非推奨
(MIIM_FTYPE | MIIM_STRINGを使用する)

fTypeメンバはメニュー項目の種類を表します。
これは以下の定数のいずれか、または組み合わせを指定します。
ただしMFT_BITMAPMFT_SEPARATORMFT_STRINGは互いに組み合わせることはできません。

定数 説明
MFT_STRING 文字列を項目に表示する。
(既定)
dwTypeDataメンバはNULL終端文字列へのポインタ、
cchメンバはその文字列の長さを表す。
MFT_BITMAP

ビットマップを項目に表示する。
dwTypeDataメンバの下位ワードをビットマップハンドルとして使用する。
cchメンバは無視される。

ビットマップを表示する場合はこのフラグよりもfMaskメンバのMIIM_BITMAPフラグおよびhbmpItemメンバの使用が推奨される。

MFT_MENUBARBREAK メニュー項目を新しい行に配置する。
ドロップダウンメニュー、サブメニュー、ショートカットメニューの場合は新しい列に配置し、縦線で区切る。
MFT_MENUBREAK メニュー項目を新しい行に配置する。
ドロップダウンメニュー、サブメニュー、ショートカットメニューの場合は新しい列に配置し、縦線で区切らない。
MFT_OWNERDRAW オーナードローメニュー項目。
MFT_RADIOCHECK チェックマークの代わりにラジオボタンマークを表示する。
(hbmpCheckedメンバがNULLの場合)
MFT_SEPARATOR セパレーター項目。
ドロップダウンメニュー、サブメニュー、ショートカットメニューで有効。
dwTypeDatacchメンバは無視される。
MFT_RIGHTORDER メニューは右から左へ読み書きされる。
(アラビア語などの右から左に読み書きする言語用)
MFT_RIGHTJUSTIFY メニュー項目の右揃え。
メニューバー内の項目にのみ有効。

fStateメンバはメニュー項目の状態を表します。
これは以下の定数のいずれか、または組み合わせを指定します。

定数 説明
MFS_ENABLED
MFS_UNCHECKED
MFS_UNHILITE
項目は有効、
チェックされていない、
強調表示(ハイライト)されていない
(初期状態)
MFS_DISABLED
MFS_GRAYED
項目は無効、 グレーアウトされた状態
MFS_CHECKED チェックマークが付けられている
MFS_HILITE 強調表示(ハイライト)されている
MFS_DEFAULT デフォルトとして設定されている
デフォルトの項目はメニュー内で一つだけ含めることができ、太字で表示される

wIDメンバはメニュー項目を識別するIDです。

hSubMenuメンバは項目に関連付けられているドロップダウンメニューまたはサブメニューのハンドルです。
これらがない場合はNULLです。

hbmpCheckedメンバは項目が選択状態の時に項目の横に表示されるビットマップのハンドルです。
このメンバがNULLの場合、デフォルトのチェックマークが使用されます。

hbmpUncheckedメンバは項目が非選択状態の時に項目の横に表示されるビットマップのハンドルです。
このメンバがNULLの場合は何も表示されません。

dwItemDataメンバは項目に関連付けられている任意の値です。
この値はプログラマが自由に使用できます。

dwTypeDataメンバは項目の内容です。
fTypeメンバの指定によって文字列のポインタであったりビットマップハンドルだったりします。
ただし上述している通り、ビットマップハンドルはこのメンバではなくMIIM_BITMAPフラグとhbmpItemメンバを使用するのがおすすめです。

cchメンバは、項目の内容が文字列である場合(MFT_STRING)の、文字列のサイズです。

hbmpItemメンバは項目に表示するビットマップのハンドルです。

GetMenu関数

メニュー項目の情報を取得/設定するにはメニューハンドルが必要です。
LoadMenu関数を使用している場合はそれをそのまま使用すれば良いですが、ウィンドウクラスに関連付けて作成されたメニューはGetMenu関数でハンドルを取得できます。

HMENU GetMenu(
 HWND hWnd
);
ウィンドウhWndに割り当てられているメニューのハンドルを返す。
メニューが存在しない場合はNULLを返す。
hWndが子ウィンドウの場合、戻り値は未定義なので使用してはならない。

サンプルコード

メニュー項目の状態を変更するサンプルです。
ビットマップを表示するためにリソースにビットマップを使用しています。
このコードをビルドするには適当なビットマップ画像を用意してください。
(16×16ピクセル推奨。自動で拡大縮小されたりはしない)


/////////////////////////////////////////////////////////////////////////////
//
// Menu
//

IDR_MENU1 MENU
BEGIN
    POPUP "編集"
    BEGIN
        MENUITEM "チェック",                 ID_40001
        MENUITEM "無効",                    ID_40002
        MENUITEM "↑の無効を解除",            ID_40003
    END
END


/////////////////////////////////////////////////////////////////////////////
//
// Bitmap
//

IDB_BITMAP1             BITMAP                  "sample.bmp"

#include <windows.h>
#include "resource.h"

//ウィンドウの生成等は省略

//ウィンドウクラスの登録
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 =  MAKEINTRESOURCE(IDR_MENU1); //メニューの登録
	wcex.lpszClassName = szWindowClass;
	wcex.hIconSm = NULL;

	return RegisterClassEx(&wcex);
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static HBITMAP hBmp;
	static HMENU hMenu;
	MENUITEMINFO mii;
	
	switch (message)
	{
	case WM_CREATE:
		//ビットマップリソースの読み込み
		hBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP1));

		//メニューハンドルの取得
		hMenu = GetMenu(hWnd);

		//項目にビットマップを表示
		mii.cbSize = sizeof(MENUITEMINFO);
		mii.fMask = MIIM_BITMAP;
		mii.hbmpItem = hBmp;
		SetMenuItemInfo(hMenu, ID_40003, 0, &mii);
		break;

	case WM_COMMAND: //コントロールの操作
		switch (LOWORD(wParam))
		{
		case ID_40001: //チェックのオン/オフ
			mii.cbSize = sizeof(MENUITEMINFO);
			mii.fMask = MIIM_STATE;
			GetMenuItemInfo(hMenu, ID_40001, 0, &mii);
			mii.fState = 
				mii.fState == MFS_CHECKED ? MFS_UNCHECKED : MFS_CHECKED;
			SetMenuItemInfo(hMenu, ID_40001, 0, &mii);
			break;
		case ID_40002: //項目を無効化する
			mii.cbSize = sizeof(MENUITEMINFO);
			mii.fMask = MIIM_STATE;
			mii.fState = MFS_DISABLED;
			SetMenuItemInfo(hMenu, ID_40002, 0, &mii);
			break;
		case ID_40003: //↑の無効化を解除
			mii.cbSize = sizeof(MENUITEMINFO);
			mii.fMask = MIIM_STATE;
			mii.fState = MFS_ENABLED;
			SetMenuItemInfo(hMenu, ID_40002, 0, &mii);
			break;
		}
		break;

	case WM_DESTROY: //ウィンドウの破棄
		DeleteObject(hBmp);
		PostQuitMessage(0);
		break;

	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

メニュー項目の状態を変更するサンプル

「チェック」項目はクリックするごとにチェック状態が切り替わります。
「無効」項目はクリックするとその項目が無効になり、以降はクリックできなくなります。
「↑の無効を解除」項目は無効化された上の「無効」項目を有効化します。
この項目にはビットマップを表示しています。