ツリー構造を作っていた時にできた副産物です。改善の余地はありますが楽です。
case WM_CREATE: { menu_t::SetDefaultMII(); MyMenu m; m.root().set( L"Menu",0);//メニューのルート。表示されない m.root().push(L"File",100);// push(タイトル, ID)の順に記述 m.root().latest().push(L"Load" ,110);//latestはこの階層で最後にpushされたアイテム m.root().latest().push(L"Save" ,120); m.root().latest().push(L"Export",130); m.root().latest().push(L"Import",140); m.root().latest().push(L"Recent",150); m.root().latest().latest().push(L"file1",151); m.root().latest().latest().push(L"file2",152); m.root().latest().latest().push(L"file3",153); m.root().push(L"Edit",200); m.root().latest().push(L"Add" ,210); m.root().latest().push(L"Delete",220); m.root().latest().push(L"Select",230); m.root().push(L"View",300); m.root().latest().push(L"Vertical" ,310); m.root().latest().push(L"Horizonal",320); m.winSetMenu(hwnd); } return 0; case WM_COMMAND://メニューがクリックされた時の処理 switch (LOWORD(wp)) { case 110: MessageBox(hwnd,L"Load",0,0); break; case 120: MessageBox(hwnd,L"Save",0,0); break; } break;
#include <vector> #include<windows.h> struct menu_t{ static MENUITEMINFO defaultMII; MENUITEMINFO mii; std::vector< menu_t > m_submenues; HMENU hmenu_this; menu_t(){} menu_t(wchar_t* title,UINT id,MENUITEMINFO _mii = defaultMII);
//このメニュー項目を設定 void set( wchar_t* title,UINT id,MENUITEMINFO _mii = defaultMII);
//このメニュー項目にサブメニューの項目を追加 void push(wchar_t* title,UINT id,MENUITEMINFO _mii = defaultMII);
//このメニュー項目のサブメニューの末尾を取得 menu_t& latest(); static void SetDefaultMII(); }; //メニュー管理クラス class MyMenu{ menu_t m_root; HMENU hMenuTop;
//メニュー登録のエントリポイント。内部でSetMenuesを呼び出す HMENU defineMenu();
//登録作業の本体。InsertMenuItemを呼び出している void SetMenues(HMENU hmenu , menu_t& menu); public: menu_t& root(); MyMenu();
//Win32apiのSetMenuを呼び出し、実際にメニューを登録する BOOL winSetMenu(HWND hwnd); };
#include "nuWinMenu.h" MENUITEMINFO menu_t::defaultMII; menu_t::menu_t(wchar_t* title,UINT id,MENUITEMINFO _mii){ set(title,id,_mii); } void menu_t::set( wchar_t* title,UINT id,MENUITEMINFO _mii){
//このメニュー項目のタイトルとIDを設定 mii = _mii; mii.fMask = MIIM_ID | MIIM_STRING; mii.wID = id; mii.dwTypeData = title; } void menu_t::push(wchar_t* title,UINT id,MENUITEMINFO _mii){
//このメニュー項目のサブメニューにアイテムを追加 m_submenues.emplace_back(title,id,_mii); } menu_t& menu_t::latest(){
//このメニュー項目に最後に追加されたサブメニュー項目を取得 return m_submenues.back(); } void menu_t::SetDefaultMII(){ memset(&defaultMII, 0, sizeof(MENUITEMINFO)); defaultMII.cbSize = sizeof(MENUITEMINFO); defaultMII.fMask = MIIM_ID | MIIM_STRING; } ///////////////////////////////////////////////////////// HMENU MyMenu::defineMenu(){ hMenuTop = CreateMenu();//メニュー作成 for(size_t i = 0; i < m_root.m_submenues.size();i++){
//トップレベルのメニュー項目を登録する SetMenues(hMenuTop,m_root.m_submenues[i]); } m_root.hmenu_this = hMenuTop; return hMenuTop; } void MyMenu::SetMenues(HMENU hmenu , menu_t& menu){ if(menu.m_submenues.size()!=0){ HMENU submenu = CreatePopupMenu();//ポップアップメニュー作成 menu.mii.hSubMenu = submenu; menu.mii.fMask |= MIIM_SUBMENU;//この項目にサブメニューがあることを指示 InsertMenuItem(hmenu, menu.mii.wID, FALSE, &menu.mii);
//サブメニューの各項目を登録 for(size_t i = 0; i < menu.m_submenues.size();i++){ SetMenues(submenu,menu.m_submenues[i]); } } else{ InsertMenuItem(hmenu, menu.mii.wID, FALSE, &menu.mii); } menu.hmenu_this = hmenu; } menu_t& MyMenu::root(){ return m_root; } MyMenu::MyMenu(){ hMenuTop = 0; } BOOL MyMenu::winSetMenu(HWND hwnd){ return SetMenu( hwnd,defineMenu() ); }