#include "stdafx.h" #include "common.h" HFONT hMenuFont; CMenuItemData::CMenuItemData(int item_index,int itemID,char *str,CMenuEx *pobj_ThisMenu,CSubMenuEx *pobj_SubMenu){ this->item_index=item_index; this->itemID=itemID; if(str){ this->str=(char *)HeapAlloc(hHeap,0,lstrlen(str)+1); lstrcpy(this->str,str); } else this->str=0; this->pobj_ThisMenu=pobj_ThisMenu; this->pobj_SubMenu=pobj_SubMenu; hIcon=0; hGrayIcon=0; } CMenuItemData::~CMenuItemData(){ //メニュー文字列 if(str) HeapDefaultFree(str); //サブメニュー オブジェクトを破棄 if(pobj_SubMenu) delete pobj_SubMenu; //アイコン if(hIcon) DestroyIcon(hIcon); //淡色アイコン if(hGrayIcon) DestroyIcon(hGrayIcon); } CMenuEx *pobj_MainMenu; CMenuEx::CMenuEx(HMENU hmenu){ hMenu=hmenu; ppobj_MenuItemData=(CMenuItemData **)HeapAlloc(hHeap,0,1); iMenuItemNum=0; } CMenuEx::~CMenuEx(){ int i; //itemDataを解放 for(i=0;istr=(char *)HeapReAlloc(hHeap,0,ppobj_MenuItemData[item_index]->str,lstrlen(str)+1); lstrcpy(ppobj_MenuItemData[item_index]->str,str); } void CMenuEx::RenameMenuItemByID(int itemID,char *str){ int i; for(i=0;iitemID==itemID){ RenameMenuItem(i,str); return; } } } void CMenuEx::RemoveItem(int item_index){ //メニューアイテムの消去 //※ポップアップメニューの消去には対応していない ::RemoveMenu(hMenu,item_index,MF_BYPOSITION); //メニューアイテム拡張データオブジェクトを破棄 delete ppobj_MenuItemData[item_index]; iMenuItemNum--; int i; for(i=item_index;iitemID==itemID){ ppobj_MenuItemData[i]->hIcon=hIcon; ///////////////////////// // 淡色アイコンを作成 ///////////////////////// ppobj_MenuItemData[i]->hGrayIcon=CreateGrayIcon(hIcon); return 1; } if(ppobj_MenuItemData[i]->pobj_SubMenu){ BOOL bResult; bResult=ppobj_MenuItemData[i]->pobj_SubMenu->SetIcon(itemID,hIcon); if(bResult) return 1; } } return 0; } int CMenuEx::FindSubMenuIndex( const std::string &itemStr ) { for( int i=0; istr ) { return i; } } return -1; } CMenuItemData *CMenuEx::AddMenuExItemData(int item_index,int itemID,char *str,CMenuEx *pobj_ThisMenu,CSubMenuEx *pobj_SubMenu){ CMenuItemData *pobj_MenuItemData; pobj_MenuItemData=new CMenuItemData(item_index,itemID,str,pobj_ThisMenu,pobj_SubMenu); ppobj_MenuItemData=(CMenuItemData **)HeapReAlloc(hHeap,0,ppobj_MenuItemData,(iMenuItemNum+1)*sizeof(CMenuItemData *)); int i; for(i=iMenuItemNum;i>item_index;i--){ ppobj_MenuItemData[i]=ppobj_MenuItemData[i-1]; } ppobj_MenuItemData[item_index]=pobj_MenuItemData; iMenuItemNum++; return pobj_MenuItemData; } void CMenuEx::InitOwnerDraw(BOOL bParent){ char temporary[MAX_PATH]; MENUITEMINFO mii; memset(&mii,0,sizeof(MENUITEMINFO)); mii.cbSize=sizeof(MENUITEMINFO); mii.fMask=MIIM_TYPE|MIIM_ID|MIIM_SUBMENU|MIIM_DATA; int nCount; nCount=GetMenuItemCount(hMenu); int i; for(i=0;iInitOwnerDraw(0); } else pobj_SubMenu=0; //拡張データをメモリに退避 CMenuItemData *pobj_MenuItemData; pobj_MenuItemData=AddMenuExItemData(i,mii.wID,temp2,this,pobj_SubMenu); mii.fType=MFT_OWNERDRAW | fType_Separator; mii.dwItemData=(ULONG_PTR)pobj_MenuItemData; SetMenuItemInfo(hMenu,i,1,&mii); } } void CMenuEx::GetItemSize(int item_index,SIZE *pSize){ if(ppobj_MenuItemData[item_index]->str){ HDC hdc; hdc = GetDC(GetDesktopWindow()); HFONT hOldFont; hOldFont = (HFONT)SelectObject(hdc, hMenuFont); GetTextExtentPoint32(hdc, ppobj_MenuItemData[item_index]->str, lstrlen(ppobj_MenuItemData[item_index]->str), pSize); SelectObject(hdc,hOldFont); ReleaseDC(GetDesktopWindow(),hdc); } else{ //セパレータのとき pSize->cx=50; pSize->cy=10; } } BOOL CMenuEx::OwnerDrawSubMenu(HMENU hSubMenu,HDC hdc,RECT *pRect,BOOL bSelect,int item_index){ int i; for(i=0;ipobj_SubMenu){ if(hSubMenu==ppobj_MenuItemData[i]->pobj_SubMenu->hMenu){ ppobj_MenuItemData[i]->pobj_SubMenu->OwnerDrawMenu(hdc,pRect,bSelect,item_index); return 1; } else{ BOOL bResult; bResult=ppobj_MenuItemData[i]->pobj_SubMenu->OwnerDrawSubMenu(hSubMenu,hdc,pRect,bSelect,item_index); if(bResult) return 1; } } } return 0; } void CMenuEx::OwnerDrawMenu(HDC hdc,RECT *pRect,BOOL bSelect,int item_index){ ///////////////////////////////// // 親メニューのオーナー描画 ///////////////////////////////// COLORREF BackColor,TextColor; RECT rc; if(bSelect){ //選択状態にある場合 HPEN hPen,hOldPen; hPen=CreatePen(PS_SOLID,0,MENUCOLOR_SELECT_LINE); hOldPen=(HPEN)SelectObject(hdc,hPen); HBRUSH hBrush,hOldBrush; hBrush=CreateSolidBrush(MENUCOLOR_SELECT_BACK); hOldBrush=(HBRUSH)SelectObject(hdc,hBrush); pRect->left++; pRect->top++; Rectangle(hdc,pRect); pRect->left--; SelectObject(hdc,hOldPen); SelectObject(hdc,hOldBrush); DeleteObject(hPen); DeleteObject(hBrush); TextColor=MENUCOLOR_TEXT; } else{ POINT pos; GetCursorPos(&pos); GetWindowRect(hOwner,&rc); pos.x-=rc.left; pos.y-=rc.top; if(HitTest(pRect,&pos)){ //ホットイメージで表示 HPEN hPen,hOldPen; hPen=CreatePen(PS_SOLID,0,MENUCOLOR_HOT_LINE); hOldPen=(HPEN)SelectObject(hdc,hPen); HBRUSH hBrush,hOldBrush; hBrush=CreateSolidBrush(MENUCOLOR_HOT_BACK); hOldBrush=(HBRUSH)SelectObject(hdc,hBrush); pRect->left++; pRect->top++; Rectangle(hdc,pRect); pRect->left--; pRect->top--; SelectObject(hdc,hOldPen); SelectObject(hdc,hOldBrush); DeleteObject(hPen); DeleteObject(hBrush); TextColor=MENUCOLOR_TEXT; } else{ BackColor=MENUCOLOR_DEFAULT_BACK; TextColor=MENUCOLOR_TEXT; //背景を塗りつぶす HBRUSH hBrush; hBrush=CreateSolidBrush(BackColor); FillRect(hdc,pRect,hBrush); DeleteObject(hBrush); } } if(ppobj_MenuItemData[item_index]->str){ rc=*pRect; rc.top+=1; SetBkMode(hdc, TRANSPARENT); SetTextColor(hdc, TextColor); HFONT hOldFont; hOldFont=(HFONT)SelectObject(hdc,hMenuFont); DrawText(hdc,ppobj_MenuItemData[item_index]->str,-1,&rc,DT_CENTER|DT_VCENTER|DT_SINGLELINE); SelectObject(hdc,hOldFont); } else{ //セパレータのとき } } CSubMenuEx::CSubMenuEx(HMENU hMenu):CMenuEx(hMenu){ } void CSubMenuEx::GetItemSize(int item_index,SIZE *pSize){ if(ppobj_MenuItemData[item_index]->str){ HDC hdc; hdc = GetDC(GetDesktopWindow()); HFONT hOldFont; hOldFont = (HFONT)SelectObject(hdc, hMenuFont); GetTextExtentPoint32(hdc, ppobj_MenuItemData[item_index]->str, lstrlen(ppobj_MenuItemData[item_index]->str), pSize); SelectObject(hdc,hOldFont); ReleaseDC(GetDesktopWindow(),hdc); pSize->cx+=50; if(pSize->cy<22) pSize->cy=22; } else{ //セパレータのとき pSize->cx=50; pSize->cy=10; } } void CSubMenuEx::OwnerDrawMenu(HDC hdc,RECT *pRect,BOOL bSelect,int item_index){ ////////////////////////////////// // サブメニューのオーナー描画 ////////////////////////////////// RECT rc; COLORREF BackColor,TextColor; int i; /////////////////////////////// // 左側のグラデーションを描画 /////////////////////////////// SIZE size; size.cx=22; size.cy=pRect->bottom-pRect->top; HBITMAP hBmp; hBmp=CreateHorzGradationBitmap(&size,RGB(254,254,251),RGB(196,196,173)); HDC memdc; memdc=CreateCompatibleDC(hdc); SelectObject(memdc,hBmp); BitBlt(hdc,pRect->left,pRect->top,size.cx,size.cy,memdc,0,0,SRCCOPY); DeleteDC(memdc); DeleteObject(hBmp); if(ppobj_MenuItemData[item_index]->str==0){ //セパレータのとき HPEN hPen,hOldPen; hPen=CreatePen(PS_SOLID,0,MENUCOLOR_DEFAULT_LINE); hOldPen=(HPEN)SelectObject(hdc,hPen); MoveToEx(hdc,pRect->left+24,pRect->top+(pRect->bottom-pRect->top)/2,NULL); LineTo(hdc,pRect->right,pRect->top+(pRect->bottom-pRect->top)/2); SelectObject(hdc,hOldPen); DeleteObject(hPen); return; } //アイテムの状態を取得 MENUITEMINFO mii; mii.cbSize=sizeof(MENUITEMINFO); mii.fMask=MIIM_STATE; GetMenuItemInfo(hMenu,item_index,1,&mii); if(bSelect&&(mii.fState&MFS_DISABLED)==0){ //ホットイメージで表示 BackColor=MENUCOLOR_HOT_BACK; HPEN hPen,hOldPen; hPen=CreatePen(PS_SOLID,0,MENUCOLOR_HOT_LINE); hOldPen=(HPEN)SelectObject(hdc,hPen); HBRUSH hBrush,hOldBrush; hBrush=CreateSolidBrush(BackColor); hOldBrush=(HBRUSH)SelectObject(hdc,hBrush); Rectangle(hdc,pRect); SelectObject(hdc,hOldPen); SelectObject(hdc,hOldBrush); DeleteObject(hPen); DeleteObject(hBrush); } else{ //マウスカーソルの座標を取得 POINT pos; GetCursorPos(&pos); //親ウィンドウのウィンドウ左上からの相対座標に変換 //(クライアント座標ではないところに注意) GetWindowRect(WindowFromDC(hdc),&rc); ScreenToClient(WindowFromDC(hdc),&pos); if(bSelect&&HitTest(pRect,&pos)==0){ //淡色状態 BackColor=MENUCOLOR_SELECT_BACK; HPEN hPen,hOldPen; hPen=CreatePen(PS_SOLID,0,MENUCOLOR_SELECT_LINE); hOldPen=(HPEN)SelectObject(hdc,hPen); HBRUSH hBrush,hOldBrush; hBrush=CreateSolidBrush(BackColor); hOldBrush=(HBRUSH)SelectObject(hdc,hBrush); Rectangle(hdc,pRect); SelectObject(hdc,hOldPen); SelectObject(hdc,hOldBrush); DeleteObject(hPen); DeleteObject(hBrush); } else{ BackColor=GetSysColor(COLOR_MENU); rc=*pRect; rc.left=pRect->left+22; rc.right=pRect->right; //背景を塗りつぶす HBRUSH hBrush; hBrush=CreateSolidBrush(BackColor); FillRect(hdc,&rc,hBrush); DeleteObject(hBrush); } } if(mii.fState&MFS_CHECKED){ //チェックマークの外枠を描画 rc=*pRect; rc.top++; rc.right=rc.left+20; rc.bottom--; HPEN hPen,hOldPen; hPen=CreatePen(PS_SOLID,0,MENUCOLOR_HOT_LINE); hOldPen=(HPEN)SelectObject(hdc,hPen); HBRUSH hBrush,hOldBrush; hBrush=CreateSolidBrush(BackColor); hOldBrush=(HBRUSH)SelectObject(hdc,hBrush); Rectangle(hdc,&rc); SelectObject(hdc,hOldPen); SelectObject(hdc,hOldBrush); DeleteObject(hPen); DeleteObject(hBrush); //チェックマークを描画 int BaseX=rc.left,BaseY=rc.top; for(i=0;i<3;i++){ SetPixel(hdc,BaseX+6+i,BaseY+9+i,MENUCOLOR_TEXT); SetPixel(hdc,BaseX+6+i,BaseY+10+i,MENUCOLOR_TEXT); } for(i=0;i<4;i++){ SetPixel(hdc,BaseX+9+i,BaseY+10-i,MENUCOLOR_TEXT); SetPixel(hdc,BaseX+9+i,BaseY+11-i,MENUCOLOR_TEXT); } } else{ if(ppobj_MenuItemData[item_index]->hIcon){ //アイコンを描画 HICON hIcon; if(mii.fState&MFS_DISABLED) hIcon=ppobj_MenuItemData[item_index]->hGrayIcon; else hIcon=ppobj_MenuItemData[item_index]->hIcon; DrawIconEx(hdc,pRect->left+1,pRect->top+3,hIcon,16,16,0,NULL,DI_NORMAL); } } //メイン文字列とショートカットキー文字列を分別 char szMain[255],szShortcut[255]; for(i=0;;i++){ if(ppobj_MenuItemData[item_index]->str[i]=='\t'){ szMain[i]=0; lstrcpy(szShortcut,ppobj_MenuItemData[item_index]->str+i+1); break; } szMain[i]=ppobj_MenuItemData[item_index]->str[i]; if(ppobj_MenuItemData[item_index]->str[i]=='\0'){ szShortcut[0]=0; break; } } rc=*pRect; rc.left=pRect->left+26; rc.right=pRect->right; HFONT hOldFont; hOldFont=(HFONT)SelectObject(hdc,hMenuFont); if(mii.fState&MFS_DISABLED){ //淡色カラー TextColor=MENUCOLOR_GRAY_TEXT; } else{ //通常カラー TextColor=MENUCOLOR_TEXT; } SetBkMode(hdc, TRANSPARENT); SetTextColor(hdc, TextColor); DrawText(hdc,szMain,-1,&rc,DT_VCENTER|DT_LEFT|DT_SINGLELINE); if(szShortcut[0]){ rc.left=rc.right-45; DrawText(hdc,szShortcut,-1,&rc,DT_VCENTER|DT_LEFT|DT_SINGLELINE); } SelectObject(hdc,hOldFont); }