メニューのメッセージ

メニューの操作時にはいくつかのメッセージが親ウィンドウに対して送信されます。

選択項目の変更

マウスオーバーやアローキーなどでメニューの選択項目を変更するとWM_MENUSELECTメッセージが送信されます。
(クリックやEnterキーでのメニュー項目の実行ではなく「現在選択されている項目」の状態の変更。背景色が変わる)

WPARAMの下位ワードにはメニュー項目のIDが格納されています。
上位ワードには以下の値が格納されています。

WPARAM上位ワード 説明
MF_GRAYED 項目はグレー表示
MF_DISABLED 項目は無効
MF_BITMAP 項目はビットマップ
MF_CHECKED 項目はチェックされている
MF_POPUP 項目はポップアップメニュー(サブメニュー)を持つ
MF_HILITE 項目は強調表示されている
MF_OWNERDRAW 項目はオーナードロー項目
MF_SYSMENU 項目はシステムメニュー内にある
MF_MOUSESELECT 項目はマウスで選択されている

これらの状態は複数同時にオンになることがあるので、ビット演算を利用して目的の値の状態を取得します。

LPARAMにはメニューハンドルが格納されています。

メニューが閉じられる時、WPARAMの上位ワードは0xffff、LPARAMはNULLになります。

このメッセージを利用して、例えば現在選択している項目の詳細な説明をステータスバーなどに表示することができます。


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

IDR_MENU1 MENU
BEGIN
    POPUP "ファイル"
    BEGIN
        MENUITEM "保存",                      ID_40001
        MENUITEM SEPARATOR
        MENUITEM "終了",                      ID_40002
    END
END

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

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

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static HWND hStatic;

	switch (message)
	{
	case WM_CREATE:
		hStatic = CreateWindow(
			L"STATIC", L"",
			WS_CHILD | WS_VISIBLE,
			0, 100, 300, 25,
			hWnd, 0, hInst, NULL);
		break;

	case WM_MENUSELECT:
		if (HIWORD(wParam) == 0xffff && lParam == NULL)
		{//メニューが閉じられた
			SetWindowText(hStatic, NULL);
			break;
		}

		switch (LOWORD(wParam))
		{
		case ID_40001:
			SetWindowText(hStatic, L"ファイルを保存します。");
			break;
		case ID_40002:
			SetWindowText(hStatic, L"プログラムを終了します。");
			break;
		}
		break;

	case WM_COMMAND: //コントロールの操作
		//省略
		break;

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

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

メッセージ表示用にスタティックコントロールをひとつ作っています。
メニューを開き、項目を選択状態にすることでその詳細をスタティックコントロール内に表示します。
選択されているメニュー項目の取得

キー押下時

メニューがアクティブ状態でアクセスキーを設定していないキーを押下したとき、WM_MENUCHARメッセージが親ウィンドウに送信されます。

WPARAMは下位ワードにユーザーが入力したキーの文字コードが格納されています。
上位ワードにはメニューの種類を示す以下の定数のどちらかが格納されています。

  • MF_POPUP - ドロップダウンメニュー、サブメニュー、ショートカットメニュー
  • MF_SYSMENU - システムメニュー

LPARAMはメニューハンドルが格納されています。

戻り値

このメッセージをウィンドウプロシージャで処理する場合、戻り値の上位ワードには以下の定数のいずれかを指定します。
下位ワードは定数の種類により意味が変わります。

定数 説明
MNC_IGNORE 入力されたキーを無視する。
システムスピーカーは短いビープ音を鳴らす。
(デフォルトの動作)
下位ワードは使用されない。
MNC_CLOSE メニューを閉じる。
下位ワードは使用されない。
MNC_EXECUTE 下位ワードに指定した番号のメニュー項目を実行するように親ウィンドウにWM_COMMANDメッセージを通知する。
(最初のメニュー項目番号は0。セパレーターなども含むので注意)
MNC_SELECT 下位ワードに指定した番号のメニュー項目を選択状態にする。
(実行はしない)

この値はMAKELRESULTマクロで作成することができます。

void MAKELRESULT(
 l,
 h
);
ウィンドウプロシージャの戻り値(LRESULT型)を作成するマクロ。
lは下位ワード、hは上位ワードとして連結される。

例えば以下のような形で使用します。


LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_MENUCHAR:
		//MNC_CLOSEを指定
		return MAKELRESULT(0, MNC_CLOSE);

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

この例では、メニュー展開中にアクセスキーに対応しないキーが押されたらメニューが閉じられます。

メニューが開かれる時

マウスクリックやアクセスキーなどによってメニューがアクティブになるとき、WM_INITMENUメッセージが親ウィンドウに送信されます。

WPARAMは開かれるメニューのハンドルが格納されています。
LPARAMは使用されません。

このメッセージは、例えば動的にメニューの項目を作成したり、項目の状態を変更したりする時に使用できます。

ショートカットメニューまたはサブメニューが開かれるときはWM_INITMENUPOPUPメッセージが親ウィンドウに送信されます。
(メニューバーの項目を選択してサブメニューがドロップダウン表示される時にも通知される)

WPARAMはポップアップされるメニュー、またはサブメニューのハンドルが格納されています。
LPARAMは下位ワードに開かれるメニューのインデックスが格納されています。
(最初は0)
上位ワードには開かれるメニューがシステムメニューの場合はTRUE、そうでなければFALSEが格納されています。