5.1 メニューを使う (3) プログラム例 #include "myWin.h" static HMENU hm,hmFile,hmEdit; enum file_ID {F_NEW = 5001, F_OPEN, F_EXIT}; enum edit_ID {E_CUT = 5010, E_COPY, E_DEL}; void procCreate(HWND hw,WPARAM wp, LPARAM lp){ MENUITEMINFO mi; hm=CreateMenu(); hmEdit=CreateMenu(); hmFile=CreateMenu(); mi.cbSize=sizeof(MENUITEMINFO); // メニューバー mi.fMask = MIIM_TYPE|MIIM_SUBMENU; mi.fType = MFT_STRING ; mi.hSubMenu = hmFile; mi.dwTypeData = TEXT("ファイル(&F)") ; InsertMenuItem(hm,0,TRUE,&mi); mi.hSubMenu = hmEdit; mi.dwTypeData = TEXT("編集(&E)") ; InsertMenuItem(hm,1,TRUE,&mi); // ファイルのサブメニュー mi.fMask = MIIM_TYPE|MIIM_ID; mi.wID = F_NEW; mi.dwTypeData= TEXT("新規作成(&N)");InsertMenuItem(hmFile,0,TRUE,&mi); mi.wID = F_OPEN; mi.dwTypeData= TEXT("開く(&O)") ;InsertMenuItem(hmFile,1,TRUE,&mi); mi.fType = MFT_SEPARATOR ; InsertMenuItem(hmFile,2,TRUE,&mi) ; mi.fType = MFT_STRING; mi.wID = F_EXIT; mi.dwTypeData= TEXT("終了(&X)") ;InsertMenuItem(hmFile,3,TRUE,&mi); // 編集のサブメニュー mi.wID = E_CUT; mi.dwTypeData= TEXT("切取(&T)") ; InsertMenuItem(hmEdit,0,TRUE,&mi); mi.wID = E_COPY; mi.dwTypeData= TEXT("複写(&C)") ; InsertMenuItem(hmEdit,1,TRUE,&mi); mi.wID = E_DEL; mi.dwTypeData= TEXT("削除(&D)") ; InsertMenuItem(hmEdit,2,TRUE,&mi); SetMenu(hw,hm); } void procCommand(HWND hw,WPARAM wp, LPARAM lp){ switch(LOWORD(wp)){ case F_NEW :MessageBox(hw,TEXT("新規"),TEXT("ファイル"),MB_OK);break; case F_OPEN:MessageBox(hw,TEXT("開く"),TEXT("ファイル"),MB_OK);break; case F_EXIT:MessageBox(hw,TEXT("終了"),TEXT("ファイル"),MB_OK);break; case E_CUT :MessageBox(hw,TEXT("切取"),TEXT("編集" ),MB_OK);break; case E_COPY:MessageBox(hw,TEXT("複写"),TEXT("編集" ),MB_OK);break; case E_DEL :MessageBox(hw,TEXT("削除"),TEXT("編集" ),MB_OK);break; } } LRESULT CALLBACK WndProc(HWND hw, UINT msg, WPARAM wp,LPARAM lp){ switch(msg){ case WM_DESTROY : PostQuitMessage(0) ; return 0; case WM_CREATE : procCreate (hw,wp,lp); return 0; case WM_COMMAND : procCommand(hw,wp,lp); return 0; } return DefWindowProc(hw,msg,wp,lp); } 5.2 メニューの階層化 (3) プログラム例 #include "myWin.h" static HMENU hm,hmFile,hmRes,hmItem; enum file_ID {F_NEW = 5001, F_OPEN, F_EXIT}; enum resv_ID {R_INP = 5010, R_DEL , R_ASG, R_CHNG, R_PLAN }; void procCreate(HWND hw,WPARAM wp, LPARAM lp){ MENUITEMINFO mi; hm=CreateMenu();hmFile=CreateMenu();hmRes=CreateMenu();hmItem=CreateMenu(); mi.cbSize=sizeof(MENUITEMINFO); // メニューバー mi.fMask=MIIM_TYPE|MIIM_SUBMENU; mi.fType=MFT_STRING; mi.hSubMenu=hmFile; mi.dwTypeData=TEXT("ファイル(&F)");InsertMenuItem(hm,0,TRUE,&mi); mi.hSubMenu=hmRes; mi.dwTypeData=TEXT("予約(&R)") ;InsertMenuItem(hm,1,TRUE,&mi); // 「ファイル」サブメニュー mi.fMask=MIIM_TYPE|MIIM_ID; mi.wID=F_NEW; mi.dwTypeData=TEXT("新規(&N)");InsertMenuItem(hmFile,0,TRUE,&mi); mi.wID=F_OPEN; mi.dwTypeData=TEXT("開く(&O)");InsertMenuItem(hmFile,1,TRUE,&mi); mi.fType=MFT_SEPARATOR ; InsertMenuItem(hmFile,2,TRUE,&mi); mi.fType=MFT_STRING; mi.wID=F_EXIT; mi.dwTypeData=TEXT("終了(&X)");InsertMenuItem(hmFile,3,TRUE,&mi); // 「予約」サブメニュー mi.wID=R_INP; mi.dwTypeData=TEXT("入力(&I)"); InsertMenuItem(hmRes,0,TRUE,&mi); mi.fMask=MIIM_TYPE|MIIM_SUBMENU; mi.hSubMenu=hmItem; mi.dwTypeData=TEXT("内訳(&T)"); InsertMenuItem(hmRes,1,TRUE,&mi); mi.fMask=MIIM_TYPE|MIIM_ID; mi.wID = R_DEL; mi.dwTypeData=TEXT("取消(&D)"); InsertMenuItem(hmRes,2,TRUE,&mi); // 「予約」「内訳」サブメニュー mi.fMask=MIIM_TYPE|MIIM_ID; mi.wID=R_ASG; mi.dwTypeData=TEXT("割当(&A)"); InsertMenuItem(hmItem,0,TRUE,&mi); mi.wID=R_CHNG; mi.dwTypeData=TEXT("変更(&C)"); InsertMenuItem(hmItem,1,TRUE,&mi); mi.wID=R_PLAN; mi.dwTypeData=TEXT("計画(&P)"); InsertMenuItem(hmItem,2,TRUE,&mi); SetMenu(hw,hm); } void procCommand(HWND hw,WPARAM wp, LPARAM lp){ switch(LOWORD(wp)){ case F_NEW :MessageBox(hw,TEXT("新規"),TEXT("ファイル" ),MB_OK);break; case F_OPEN:MessageBox(hw,TEXT("開く"),TEXT("ファイル" ),MB_OK);break; case F_EXIT:MessageBox(hw,TEXT("終了"),TEXT("ファイル" ),MB_OK);break; case R_INP :MessageBox(hw,TEXT("入力"),TEXT("予約" ),MB_OK);break; case R_DEL :MessageBox(hw,TEXT("取消"),TEXT("予約" ),MB_OK);break; case R_ASG :MessageBox(hw,TEXT("割当"),TEXT("予約-内訳"),MB_OK);break; case R_CHNG:MessageBox(hw,TEXT("変更"),TEXT("予約-内訳"),MB_OK);break; case R_PLAN:MessageBox(hw,TEXT("計画"),TEXT("予約-内訳"),MB_OK);break; } } LRESULT CALLBACK WndProc(HWND hw, UINT msg, WPARAM wp,LPARAM lp){ switch(msg){ case WM_DESTROY : PostQuitMessage(0) ; return 0; case WM_CREATE : procCreate (hw,wp,lp);return 0; case WM_COMMAND : procCommand(hw,wp,lp);return 0; } return DefWindowProc(hw,msg,wp,lp); } 5.3 ポップアップメニュー (procCommandまで5.2節と同じ。したがって省略) void procPopUpMenu(HWND hw, LPARAM lp, int index){ POINT p; p.x=LOWORD(lp); p.y=HIWORD(lp); ClientToScreen(hw, &p) ; HMENU hmSub=GetSubMenu(hm,index); TrackPopupMenu(hmSub, TPM_LEFTALIGN|TPM_BOTTOMALIGN, p.x,p.y,0,hw,NULL); } void procRButtonUp(HWND hw, WPARAM wp,LPARAM lp){ procPopUpMenu(hw, lp, 1); } void procLButtonUp(HWND hw, WPARAM wp,LPARAM lp){ procPopUpMenu(hw, lp, 0); } LRESULT CALLBACK WndProc(HWND hw, UINT msg, WPARAM wp,LPARAM lp){ switch(msg){ case WM_DESTROY : PostQuitMessage(0) ;return 0; case WM_CREATE : procCreate (hw,wp,lp);return 0; case WM_COMMAND : procCommand (hw,wp,lp);return 0; case WM_RBUTTONUP: procRButtonUp(hw,wp,lp);return 0; case WM_LBUTTONUP: procLButtonUp(hw,wp,lp);return 0; } return DefWindowProc(hw,msg,wp,lp); } 5.4 メニューの操作 (1) メニュー情報の変更 #include "myWin.h" static HMENU hm,hmFile,hmEdit; enum file_ID {F_NEW = 5001, F_OPEN, F_EXIT}; enum edit_ID {U_TOKYO = 5010, U_GUMMA, U_CHIBA}; static MENUITEMINFO mi; void procCreate(HWND hw,WPARAM wp, LPARAM lp){ hm = CreateMenu(); hmEdit = CreateMenu(); hmFile = CreateMenu(); mi.cbSize = sizeof(MENUITEMINFO) ; mi.fMask = MIIM_TYPE|MIIM_SUBMENU; mi.fType = MFT_STRING ; mi.hSubMenu=hmFile; mi.dwTypeData= TEXT("ファイル(&F)") ; InsertMenuItem(hm,0,TRUE,&mi); mi.hSubMenu = hmEdit; mi.dwTypeData= TEXT("変更(&U)") ; InsertMenuItem(hm,1,TRUE,&mi); //「ファイル」サブメニュー mi.fMask = MIIM_TYPE|MIIM_ID; mi.wID = F_NEW; mi.dwTypeData= TEXT("新規作成(&N)") ; InsertMenuItem(hmFile,0,TRUE,&mi); mi.wID = F_OPEN; mi.dwTypeData= TEXT("開く(&O)") ; InsertMenuItem(hmFile,1,TRUE,&mi); mi.fType = MFT_SEPARATOR ; InsertMenuItem(hmFile,2,TRUE,&mi); mi.fType = MFT_STRING; mi.wID = F_EXIT; mi.dwTypeData= TEXT("終了(&X)") ;InsertMenuItem(hmFile,3,TRUE,&mi); //「変更」サブメニュー mi.wID=U_TOKYO; mi.dwTypeData= TEXT("東京(&T)") ; InsertMenuItem(hmEdit,0,TRUE,&mi); mi.wID = U_GUMMA; mi.dwTypeData= TEXT("群馬(&G)") ; InsertMenuItem(hmEdit,1,TRUE,&mi); mi.wID = U_CHIBA; mi.dwTypeData= TEXT("千葉(&C)") ; InsertMenuItem(hmEdit,2,TRUE,&mi); SetMenu(hw,hm); } void procMenuChange(HWND hw,int menuID ){ mi.fMask=MIIM_STATE; if(mi.fState == MFS_CHECKED) mi.fState=MFS_UNCHECKED; else mi.fState=MFS_CHECKED; SetMenuItemInfo(hm,menuID,FALSE,&mi); } void procCommand(HWND hw,WPARAM wp, LPARAM lp){ int CD=LOWORD(wp); switch(CD){ case F_NEW :MessageBox(hw,TEXT("新規"),TEXT("ファイル"),MB_OK);break; case F_OPEN:MessageBox(hw,TEXT("開く"),TEXT("ファイル"),MB_OK);break; case F_EXIT:MessageBox(hw,TEXT("終了"),TEXT("ファイル"),MB_OK);break; case U_TOKYO: case U_GUMMA: case U_CHIBA:procMenuChange(hw,CD);break; } } LRESULT CALLBACK WndProc(HWND hw, UINT msg, WPARAM wp,LPARAM lp){ switch(msg){ case WM_DESTROY : PostQuitMessage(0) ; return 0; case WM_CREATE : procCreate (hw,wp,lp); return 0; case WM_COMMAND : procCommand(hw,wp,lp); return 0; } return DefWindowProc(hw,msg,wp,lp); } (2) メニューの削除 前項(1)のプログラムのprocMenuChangeだけを次のように書き直して実行。 void procMenuChange(HWND hw,int menuID ){ DeleteMenu(hm,menuID, MF_BYCOMMAND); DrawMenuBar(hw); } (3) メニューの解放 #include "myWin.h" static HMENU hm1,hm2 ,hmHokkaido,hmKyushu; static MENUITEMINFO mi; enum kyushu_ID {FUKUOKA = 5001, NAGASAKI, KUMAMOTO}; enum hokkaido_ID {SAPPORO = 5010, OBIHIRO , KITAMI }; void procCreate(HWND hw,WPARAM wp, LPARAM lp){ hm1=CreateMenu(); hm2=CreateMenu(); hmHokkaido=CreateMenu(); hmKyushu=CreateMenu(); mi.cbSize=sizeof(MENUITEMINFO); mi.fMask=MIIM_TYPE|MIIM_SUBMENU; mi.fType=MFT_STRING; mi.hSubMenu=hmHokkaido; mi.dwTypeData=TEXT("北海道(&H)");InsertMenuItem(hm1,0,TRUE,&mi); mi.hSubMenu=hmKyushu; mi.dwTypeData=TEXT("九州(&Q)") ;InsertMenuItem(hm2,0,TRUE,&mi); mi.fMask=MIIM_TYPE|MIIM_ID; mi.wID=SAPPORO; mi.dwTypeData=TEXT("札幌(&S)");InsertMenuItem(hmHokkaido,0,TRUE,&mi); mi.wID=OBIHIRO; mi.dwTypeData=TEXT("帯広(&O)");InsertMenuItem(hmHokkaido,1,TRUE,&mi); mi.wID=KITAMI; mi.dwTypeData=TEXT("北見(&K)");InsertMenuItem(hmHokkaido,2,TRUE,&mi); mi.wID=FUKUOKA; mi.dwTypeData=TEXT("福岡(&F)");InsertMenuItem(hmKyushu,0,TRUE,&mi); mi.wID=NAGASAKI; mi.dwTypeData=TEXT("長崎(&N)");InsertMenuItem(hmKyushu,1,TRUE,&mi); mi.wID=KUMAMOTO; mi.dwTypeData=TEXT("熊本(&K)");InsertMenuItem(hmKyushu,2,TRUE,&mi); } void procLButtonDown(HWND hw, WPARAM wp,LPARAM lp){ SetMenu(hw,hm1); } void procRButtonDown(HWND hw, WPARAM wp,LPARAM lp){ SetMenu(hw,hm2); } LRESULT CALLBACK WndProc(HWND hw, UINT msg, WPARAM wp,LPARAM lp){ switch(msg){ case WM_DESTROY : SetMenu(hw,NULL); DestroyMenu(hmHokkaido); DestroyMenu(hmKyushu); PostQuitMessage(0); return 0; case WM_CREATE : procCreate (hw,wp,lp);return 0; case WM_LBUTTONDOWN: procLButtonDown(hw,wp,lp);return 0; case WM_RBUTTONDOWN: procRButtonDown(hw,wp,lp);return 0; } return DefWindowProc(hw,msg,wp,lp); } 5.5 システムメニュー (2) ユーザ定義項目の追加 #include "myWin.h static HMENU sysMenu; static MENUITEMINFO mi; void procCreate(HWND hw,WPARAM wp, LPARAM lp){ sysMenu=GetSystemMenu(hw,FALSE); mi.cbSize = sizeof(MENUITEMINFO); mi.fMask = MIIM_TYPE|MIIM_ID; mi.wID = 5000; mi.fType = MFT_STRING; mi.dwTypeData = TEXT("SysMenuTest"); InsertMenuItem(sysMenu,0,TRUE,&mi); } void procSysCommand(HWND hw, WPARAM wp,LPARAM lp){ switch(LOWORD(wp)){ case 5000:GetSystemMenu(hw,TRUE);break; } } LRESULT CALLBACK WndProc(HWND hw, UINT msg, WPARAM wp,LPARAM lp){ switch(msg){ case WM_DESTROY : PostQuitMessage(0) ;return 0; case WM_CREATE : procCreate (hw,wp,lp);return 0; case WM_SYSCOMMAND : procSysCommand(hw,wp,lp); } return DefWindowProc(hw,msg,wp,lp); } 5.6 リソースファイルによるメニュー (2) インクルードファイルおよびリソースファイル例 【インクルードファイル(menutest.h)】 /* menutest.h*/ #define TOKYO 1000 #define SAITAMA 1001 #define GUNMA 1002 #define KANAGAWA 1003 #define CHIBA 1004 #define TOCHIGI 1005 #define IBARAGI 1006 #define KYOTO 2001 #define OSAKA 2002 #define NARA 2003 リソースファイル(ファイル名:menutest.rc) /* menutest.rc */ #include "menutest.h" KEN MENU { POPUP "関東" { POPUP "北関東" { MENUITEM "埼玉" , SAITAMA MENUITEM "栃木" , TOCHIGI MENUITEM "茨城" , IBARAGI } MENUITEM SEPARATOR POPUP "南関東"{ MENUITEM "東京" , TOKYO MENUITEM "神奈川", KANAGAWA MENUITEM "千葉" , CHIBA } } POPUP "近畿" { MENUITEM "京都" , KYOTO MENUITEM "大阪" , OSAKA MENUITEM "奈良" , NARA } } (3) プログラム例 #include #include "menutest.h" void procCreate(HWND hw,WPARAM wp, LPARAM lp){ SetMenu(hw, LoadMenu(((LPCREATESTRUCT)(lp))->hInstance, TEXT("KEN"))); }