前回までは、ポップアップメニューのオーナードローをしました。
今回は、メニューバーのオーナードローをします。
メニュー・オーナードロー2 - インコのWindowsSDK で作成したソースを修正します。
流れ
関数: MyRegisterClass()
WNDCLASSEX構造体のlpszMenuNameメンバをNULLにします。
これにより、メニューバーが表示されなくなります。
リソースも、メニューに関する箇所を削除します。
WM_CREATE
1.CreateMenu()でメニューを作成
2.CreatePopupMenu()で、ポップアップメニューを作成
3.MENUITEMINFO構造体をセット。
先に構造体を初期化しておきます。
4.MInsertMenuItem()で、メニューの項目を追加。
5.SetMenu()で、新しいメニューを指定されたウィンドウに割り当てます。
BOOL SetMenu( HWND hWnd, // ウィンドウハンドル HMENU hMenu // メニューハンドル );
ソースコードの入力
ソースコードは下記のように入れてください。
test.cpp
#define _WIN32_WINNT 0x0501 #include <windows.h> #include "resource.h" #define MENU_WIDTH_PLUS 5 // グローバル変数: HINSTANCE hInst; // 現在のインターフェイス HMENU hMenu; // メニューのハンドル HMENU hSubMenu1; // メニューのハンドル HMENU hSubMenu2; // メニューのハンドル LPMEASUREITEMSTRUCT lpMI; // LPMEASUREITEMSTRUCT構造体 LPDRAWITEMSTRUCT lpDI; // DRAWITEMSTRUCT構造体 // このコード モジュールに含まれる関数の宣言を転送します: 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; hInst = hInstance; // グローバル変数にインスタンス処理を格納します。 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_COMMAND - アプリケーション メニューの処理 // WM_DESTROY - 中止メッセージを表示して戻る // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; HDC hdc; RECT rc; SIZE sz; LPCTSTR str[] = {TEXT("アプリケーションの終了(&X)"), TEXT("バージョン情報(&A)...")}; NONCLIENTMETRICS NCMetrics; HFONT hFont, hFontOld; static LOGFONT g_menufont; static int g_icon_vx, g_icon_vy; static DWORD g_menu_backcolor; static DWORD g_menu_textcolor; static HICON hIcon; HBRUSH hBrush; 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 | MFT_OWNERDRAW; mi.wID = IDM_EXIT; InsertMenuItem(hSubMenu1, 0, TRUE, &mi); mi.wID = IDM_ABOUT; InsertMenuItem(hSubMenu2, 0, TRUE, &mi); SetMenu(hWnd, hMenu); NCMetrics.cbSize = sizeof(NONCLIENTMETRICS); SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &NCMetrics, 0); g_menufont = NCMetrics.lfMenuFont; g_icon_vx = (int)GetSystemMetrics(SM_CXSMICON); g_icon_vy = (int)GetSystemMetrics(SM_CYSMICON); hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_TEST)); g_menu_backcolor = GetSysColor(COLOR_HIGHLIGHT); g_menu_textcolor = GetSysColor(COLOR_HIGHLIGHTTEXT); break; case WM_MEASUREITEM: lpMI = (LPMEASUREITEMSTRUCT)lParam; hdc = GetDC(hWnd); hFont = CreateFontIndirect(&g_menufont); hFontOld = (HFONT)SelectObject(hdc, hFont); GetTextExtentPoint32(hdc, str[lpMI->itemData], lstrlen(str[lpMI->itemData]) - 1, &sz); lpMI->itemWidth = sz.cx + g_icon_vx + MENU_WIDTH_PLUS; lpMI->itemHeight = sz.cy + 5; ReleaseDC(hWnd, hdc); break; case WM_DRAWITEM: lpDI = (LPDRAWITEMSTRUCT)lParam; rc = lpDI->rcItem; hdc = lpDI->hDC; hFont = CreateFontIndirect(&g_menufont); hFontOld = (HFONT)SelectObject(hdc, hFont); switch (lpDI->itemID) { case IDM_EXIT: if (lpDI->itemState & ODS_SELECTED) { hBrush = CreateSolidBrush(g_menu_backcolor); SetBkColor(hdc, g_menu_backcolor); SetTextColor(hdc, g_menu_textcolor); } else { hBrush = CreateSolidBrush(GetBkColor(hdc)); } FillRect(hdc, &rc, hBrush); DeleteObject(hBrush); DrawIconEx(hdc, rc.left, rc.top + 1, hIcon, g_icon_vx, g_icon_vy, 0, NULL, DI_IMAGE | DI_MASK); TextOut(hdc, rc.left + g_icon_vx + MENU_WIDTH_PLUS, rc.top + 2, str[0], lstrlen(str[0])); break; case IDM_ABOUT: if (lpDI->itemState & ODS_SELECTED) { hBrush = CreateSolidBrush(g_menu_backcolor); SetBkColor(hdc, g_menu_backcolor); SetTextColor(hdc, g_menu_textcolor); } else { hBrush = CreateSolidBrush(GetBkColor(hdc)); } FillRect(hdc, &rc, hBrush); DeleteObject(hBrush); DrawIconEx(hdc, rc.left, rc.top + 1, hIcon, g_icon_vx, g_icon_vy, 0, NULL, DI_IMAGE | DI_MASK); TextOut(hdc, rc.left + g_icon_vx + MENU_WIDTH_PLUS, rc.top + 2, str[1], lstrlen(str[1])); break; } SelectObject(hdc, hFontOld); DeleteObject(hFont); 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 IDI_TEST 107 #define IDC_HP 109
未使用の変数を削除しました。
test.rc リソースファイル
#include "resource.h" ///////////////////////////////////////////////////////////////////////////// // // アイコン // IDI_TEST ICON "test.ico"
メニューを削除しました。