// MenuEx.cpp: implementation of the CMenuEx class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "MenuEx.h" #include "./menuex.h" #include "resource.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// IMPLEMENT_DYNAMIC( CMenuEx, CMenu ) CMenuEx::CMenuEx() : m_szImage(16,15) , nCheckBmpID(0) , m_nMenuID(0) { //m_colMenu =::GetSysColor(COLOR_MENU); //设置默认颜色 m_colMenu = RGB(239,243,255); m_colText =RGB( 10,125,255); m_colTextSelected =::GetSysColor(COLOR_HIGHLIGHTTEXT); m_crCurSelBorder = RGB(49,106,197); m_crCurSelRect = RGB( 193, 210, 238 ); m_crLeftErectRect = RGB( 62, 4, 251 ); m_crSeparator = RGB( 255,0,255 ) ; nCheckBmpID = IDB_BMP_CHECK; m_bHasImageLeft =FALSE; m_nSeparator = 10; m_nMenuID = ID_APPLY; } CMenuEx::~CMenuEx() { m_ImageList.DeleteImageList(); if(m_bHasImageLeft) m_bmpImageLeft.DeleteObject(); //释放所有的子菜单 for(int i = 0; i < m_SubMenuArr.GetSize(); i++) { CMenuEx *pSubMenu = m_SubMenuArr.GetAt(i); delete pSubMenu; } //释放所有的菜单项 for(i = 0; i < m_MenuItemArr.GetSize(); i++) { MENUITEM *pMenuItem = m_MenuItemArr.GetAt(i); delete pMenuItem; } //销毁菜单 DestroyMenu(); } ///////////////////////////////////////////////// //当菜单项为不可用时绘制灰色的文本 void CMenuEx::GrayString(CDC *pDC, const CString &str, const CRect rect) { CRect rt(rect); //int nMode =pDC->SetBkMode(TRANSPARENT); rt.left +=1; rt.top +=1; pDC->SetTextColor(RGB(255,255,255)); pDC->DrawText(str,&rt,DT_EXPANDTABS|DT_VCENTER|DT_SINGLELINE); rt.left -=1; rt.top -=1; pDC->SetTextColor(RGB(127,127,127)); pDC->DrawText(str,&rt,DT_EXPANDTABS|DT_VCENTER|DT_SINGLELINE); //pDC->SetBkMode(nMode); } ///////////////////////////////////////////////// //绘制菜单项位图 void CMenuEx::DrawMenuItemImage(CDC *pDC, CRect &rect, BOOL bSelected, BOOL bChecked, BOOL bGrayed, BOOL bHasImage,LPMENUITEM lpItem) { CRect rt(rect.left ,rect.top ,rect.left + m_szImage.cx + 4, rect.top + m_szImage.cy + 4); if( bChecked ) { if(bGrayed) { //菜单不可用 GrayString(pDC," √",rt); } else { rt.InflateRect(-2,-2); //画出"√" pDC->SetBkMode(TRANSPARENT); pDC->SetTextColor(m_colText); CDC dc; dc.CreateCompatibleDC( pDC ); CBitmap bitmap; bitmap.LoadBitmap( nCheckBmpID ); dc.SelectObject( &bitmap ); pDC->BitBlt( rt.left , rt.top , rt.Width() + 1, rt.Height() + 1, &dc, 0,0,SRCCOPY ); dc.DeleteDC(); bitmap.DeleteObject(); } rect.left +=m_szImage.cx + 4 +2 ; return ; } else { pDC->BeginPath(); CDC MemDC; MemDC.CreateCompatibleDC( pDC ); CBitmap bmp; bmp.LoadBitmap( IDB_BMP_CHECK_HIGH ); MemDC.SelectObject( &bmp ); pDC->BitBlt( rect.left + 2, rect.top + 2, rect.Width(), rect.Height(), &MemDC, 0, 0, SRCCOPY ); MemDC.DeleteDC(); bmp.DeleteObject(); pDC->EndPath(); pDC->SelectClipPath( RGN_DIFF ); } if(bHasImage) { CPoint pt(rt.left+2 , rt.top+2 ); if(bSelected) { //pt.x = rt.left + 1; pt.y = rt.top + 1; } UINT uStyle =ILD_TRANSPARENT; //CImageList::Draw()绘制位图的风格 if(bGrayed) { uStyle |=ILD_BLEND50; //菜单不可用所以位图较暗 } //pDC->FillSolidRect(rect.left + 2,rect.top + 2,m_szImage.cx,m_szImage.cy,0); //lpItem->pImageList->Draw(pDC,lpItem->uIndex,pt,uStyle); //在菜单项中绘制位图 //调整可绘制矩形的大小 //4:位图外接矩形比位图大4 //2:菜单文本与位图外接矩形的间隔为2 //rect.left +=m_szImage.cx + 4 + 2; } } ///////////////////////////////////////////////// //绘制菜单项文本 //参数:rect:立体矩形的RECT // rtText:菜单文本的RECT void CMenuEx::TextMenu(CDC *pDC, CRect rect,CRect rcText,BOOL bSelected, BOOL bGrayed, LPMENUITEM lpItem) { if(bSelected) { CRect rcItem( rect ); CPen BorderPen,*pOldPen; BorderPen.CreatePen(PS_SOLID,1,m_crCurSelBorder); CBrush BKBrush,*pOldBrush; BKBrush.CreateSolidBrush( m_crCurSelRect ); pOldPen = pDC->SelectObject(&BorderPen); pOldBrush = pDC->SelectObject(&BKBrush); pDC->Rectangle(&rcItem); pDC->SelectObject(pOldPen); pDC->SelectObject(pOldBrush); } if(bGrayed) { CPoint pt(rcText.left + 3,rcText.top + 3); CSize si(rcText.Width(),rcText.Height()); pDC->DrawState(pt, si, lpItem->strText, DSS_DISABLED, TRUE, 0, (HBRUSH)NULL); } else { CRect rect( rcText ); rect.SetRect( rect.left + 3, rect.top + 3, rect.right + 3, rect.bottom + 3 ); pDC->DrawText( lpItem->strText, rect, DT_LEFT | DT_EXPANDTABS | DT_VCENTER ); } } void CMenuEx::DrawItem(LPDRAWITEMSTRUCT lpDIS) { TRACE1( "/nm_MenuItemArr.GetSize() == %d", m_MenuItemArr.GetSize() ); CDC dc; LPMENUITEM lpItem; CRect rect(lpDIS->rcItem); dc.Attach(lpDIS->hDC); lpItem =(LPMENUITEM)lpDIS->itemData; //被选中的话,使用被选中的文本颜色 if( lpDIS->itemState & ODS_SELECTED ) dc.SetTextColor( m_colTextSelected ); else dc.SetTextColor( m_colText ); //设定背景色 CBrush brush(m_colMenu); dc.FillRect(&rect, &brush); CRect rcLeft = rect; rcLeft.right = rcLeft.left + m_szImage.cx + 5; CRect rcText = rect; rcText.left += (m_szImage.cx + 10); dc.FillSolidRect(&rcLeft,m_crLeftErectRect); //填充左边竖条框的颜色 //设定显示模式 dc.SetBkMode(TRANSPARENT); if(lpItem->uID==0)//分隔条 { rcText.top =rcText.Height()/2+rcText.top - 2 ; rcText.bottom =rcText.top +2; rcText.right -=2; rcText.left -= 3; CPen pen( PS_DOT , 0, m_crSeparator ), *pOldPen = NULL; pOldPen = dc.SelectObject( &pen ); dc.MoveTo( rcText.left , (int)( (rcText.top + rcText.bottom) / 2.0 ) ); dc.LineTo( rcText.right , (int)( (rcText.top + rcText.bottom) / 2.0 ) ); dc.SelectObject( pOldPen ); pen.DeleteObject(); } else //弹出式菜单和正常菜单项 { BOOL bSelected = lpDIS->itemState & ODS_SELECTED; BOOL bChecked = lpDIS->itemState & ODS_CHECKED; BOOL bGrayed = lpDIS->itemState & ODS_GRAYED; BOOL bHasImage = (lpItem->uIndex != -1); //绘制菜单文本 TextMenu(&dc,rect,rcText,bSelected,bGrayed,lpItem); //绘制菜单位图 DrawMenuItemImage( &dc, rect, bSelected, bChecked, bGrayed, bHasImage, lpItem ); } if( m_nMenuID == lpDIS->itemID ) { dc.BeginPath(); CDC MemDC; MemDC.CreateCompatibleDC( &dc ); CBitmap bmp; bmp.LoadBitmap( IDB_BMP_CHECK_HIGH ); MemDC.SelectObject( &bmp ); dc.BitBlt( rect.left + 2, rect.top + 2, rect.Width(), rect.Height(), &MemDC, 0, 0, SRCCOPY ); MemDC.DeleteDC(); bmp.DeleteObject(); dc.EndPath(); dc.SelectClipPath( RGN_DIFF ); } dc.SetBkMode(OPAQUE); dc.Detach(); } ////////////////////////////////////////////////////////// void CMenuEx::MeasureItem(LPMEASUREITEMSTRUCT lpMIS) { MENUITEM *lpItem =(LPMENUITEM)lpMIS->itemData; if(lpItem->uID==0)//分隔条 { lpMIS->itemHeight =m_nSeparator; } else { CDC *pDC =AfxGetMainWnd()->GetDC(); CString strText=lpItem->strText; CSize size; size=pDC->GetTextExtent(lpItem->strText); lpMIS->itemWidth = size.cx /*+m_szImage.cx+6 */ ; lpMIS->itemWidth += m_szImage.cx; //lpMIS->itemWidth += 30; if(/*m_bHasImageLeft &&*/ lpItem->uPositionImageLeft >= 0) lpMIS->itemWidth += 30; if(lpItem->uID == -1) { lpMIS->itemWidth += 10; } lpMIS->itemHeight =m_szImage.cy+4; AfxGetMainWnd()->ReleaseDC(pDC); } } void CMenuEx::SetImageLeft(UINT idBmpLeft,BOOL bIsPopupMenu) { if(m_bHasImageLeft) m_bmpImageLeft.DeleteObject(); m_bmpImageLeft.LoadBitmap(idBmpLeft); m_bHasImageLeft = TRUE; BITMAP bmpInfo; m_bmpImageLeft.GetBitmap(&bmpInfo); m_szImageLeft.cx =bmpInfo.bmWidth; m_szImageLeft.cy =bmpInfo.bmHeight; //TRACE1( "m_MenuItemArr.GetSize(); = %d", m_MenuItemArr.GetSize() ); for(int i=0; i < m_MenuItemArr.GetSize(); i++) { MENUITEM *pMenuItem = m_MenuItemArr.GetAt(i); pMenuItem->uPositionImageLeft = 1; } } static int nCOUNT; void CMenuEx::SetTextColor(COLORREF crColor) { nCOUNT ++; //TRACE2( "COUNT = %d, menu Count = %d /n",nCOUNT,this->GetMenuItemCount() ); m_colText =crColor; for(int i = 0; i < m_SubMenuArr.GetSize(); i++) { CMenuEx *pSubMenu = m_SubMenuArr.GetAt(i); pSubMenu->SetTextColor(crColor); } } void CMenuEx::SetBackColor(COLORREF crColor) { m_colMenu =crColor; for(int i = 0; i < m_SubMenuArr.GetSize(); i++) { CMenuEx *pSubMenu = m_SubMenuArr.GetAt(i); pSubMenu->SetBackColor(crColor); } } void CMenuEx::SetHighLightColor(COLORREF crColor) { m_colTextSelected =crColor; for(int i = 0; i < m_SubMenuArr.GetSize(); i++) { CMenuEx *pSubMenu = m_SubMenuArr.GetAt(i); pSubMenu->SetHighLightColor(crColor); } } void CMenuEx::LoadToolBar(UINT uToolBar, UINT uFace) { CToolBar m_wndToolBar; if (!m_wndToolBar.CreateEx(AfxGetMainWnd(), TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_wndToolBar.LoadToolBar(uToolBar)) { return; } //GetImageFromToolBar(uToolBar,&m_wndToolBar,RGB(192,192,192),0); //InitMenu(this,uToolBar,&m_wndToolBar,uFace); } BOOL CMenuEx::RemoveMenuEx(UINT nPosition, UINT nFlags) { UINT uItemID = 0; if(nFlags & MF_BYPOSITION) { uItemID = GetMenuItemID((int)nPosition); } else { uItemID = nPosition; } if((int) uItemID >= 0) //普通菜单项或分割条 { for(int i = 0; i < m_MenuItemArr.GetSize(); i++) { MENUITEM *pMenuItem = m_MenuItemArr.GetAt(i); if(pMenuItem->uID == uItemID) { m_MenuItemArr.RemoveAt(i); break; } } } else //子菜单 { } return CMenu::RemoveMenu(nPosition,nFlags); } BOOL CMenuEx::AppendMenuEx(UINT nFlags, UINT nIDNewItem, LPCTSTR lpszNewItem) { MENUITEM *pMenuItem = new MENUITEM; pMenuItem->strText = lpszNewItem; pMenuItem->uID = nIDNewItem; pMenuItem->uIndex = -1; pMenuItem->uPositionImageLeft = -1; /* UINT uNewFlags = 0; if(nFlags & MF_CHECKED) uNewFlags |= MF_CHECKED; if(nFlags & MF_UNCHECKED) uNewFlags |= MF_UNCHECKED; if(nFlags & MF_SEPARATOR) uNewFlags |= MF_SEPARATOR; uNewFlags |= MF_OWNERDRAW;*/ nFlags &= ~MF_STRING; nFlags |= MF_OWNERDRAW; m_MenuItemArr.Add(pMenuItem); return CMenu::AppendMenu(nFlags,nIDNewItem,(LPCTSTR)pMenuItem); } BOOL CMenuEx::LoadMenu(UINT uMenu) { //重新读入菜单,创建为popup菜单,才能自画(由框架调用MesureItem() 和 DrawItem() HMENU hMenu = ::CreateMenu(); this->Attach(hMenu); CMenu Menu; //临时菜单 UINT uID; Menu.LoadMenu(uMenu); for(int i = 0; i < (int)Menu.GetMenuItemCount(); i++) { uID = Menu.GetMenuItemID( i ); if(uID == 0) //分隔符 { ::AppendMenu(hMenu,MF_SEPARATOR,0,NULL); } else if((int)uID == -1) //弹出菜单(即子菜单) { CMenu *pSubMenu = Menu.GetSubMenu(i); //创建子菜单 HMENU hSubMenu = ::CreatePopupMenu(); CString strPopup; Menu.GetMenuString(i,strPopup,MF_BYPOSITION); ::InsertMenu(hMenu,i,MF_BYPOSITION | MF_POPUP | MF_STRING,(UINT)hSubMenu,strPopup); //对子菜单递归调用ChangeMenuStyle(),把子菜单改为MF_OWNERDRAW风格 ChangeMenuStyle(pSubMenu,hSubMenu); } else //正常的菜单项 { CString strText; Menu.GetMenuString(uID,strText,MF_BYCOMMAND); AppendMenu(MF_STRING,uID,strText); } } Menu.DestroyMenu(); //销毁临时菜单 return TRUE; } void CMenuEx::ChangeMenuStyle(CMenu *pMenu,HMENU hNewMenu) { //关联为CMenuEx(关联为CMenuEx后才能自动重画 //原因不明(CMenu封装的结果?) CMenuEx *pNewMenu; pNewMenu = new CMenuEx; pNewMenu->Attach( hNewMenu ); m_SubMenuArr.Add(pNewMenu); UINT uID; int nItemCount = pMenu->GetMenuItemCount(); for(int i = 0; i < nItemCount; i++) { uID = pMenu->GetMenuItemID(i); if(uID == 0) //分隔符 { ::AppendMenu(hNewMenu,MF_SEPARATOR,0,NULL); //pNewMenu->AppendMenu(MF_SEPARATOR,0,NULL); CString strText; MENUITEM *pMenuItem = new MENUITEM; pMenuItem->uID = 0; pMenuItem->uIndex = -1; pMenuItem->uPositionImageLeft = -1; pMenuItem->pImageList = &m_ImageList; m_MenuItemArr.Add(pMenuItem); ::ModifyMenu(hNewMenu,i,MF_BYPOSITION | MF_OWNERDRAW,-1,(LPCTSTR)pMenuItem); //pNewMenu->AppendMenuEx(MF_SEPARATOR,0,NULL); } else if(uID == -1) //弹出菜单(即子菜单) { CMenu *pSubMenu = pMenu->GetSubMenu(i); HMENU hPopMenu = ::CreatePopupMenu(); CString strPopup; pMenu->GetMenuString(i,strPopup,MF_BYPOSITION); ::InsertMenu(hNewMenu,i,MF_BYPOSITION | MF_POPUP,(UINT)hPopMenu,strPopup); MENUITEM *pMenuItem = new MENUITEM; pMenuItem->uID = -1; pMenuItem->strText = strPopup; pMenuItem->uIndex = -1; pMenuItem->uPositionImageLeft = -1; pMenuItem->pImageList = &m_ImageList; m_MenuItemArr.Add(pMenuItem); ::ModifyMenu(hNewMenu,i,MF_BYPOSITION | MF_OWNERDRAW,-1,(LPCTSTR)pMenuItem); //pNewMenu->ModifyMenuEx(i,MF_BYPOSITION,-1,strPopup); ChangeMenuStyle(pSubMenu,hPopMenu); } else //正常的菜单项 { CString strText; pMenu->GetMenuString(uID,strText,MF_BYCOMMAND); MENUITEM *pMenuItem = new MENUITEM; pMenuItem->uID = pMenu->GetMenuItemID(i); pMenu->GetMenuString(pMenuItem->uID,pMenuItem->strText,MF_BYCOMMAND); pMenuItem->uIndex = -1; pMenuItem->uPositionImageLeft = -1; pMenuItem->pImageList = &m_ImageList; //::AppendMenu(hNewMenu,MF_STRING,uID,(LPCTSTR)pMenuItem->strText); m_MenuItemArr.Add(pMenuItem); UINT uState = pMenu->GetMenuState(i,MF_BYPOSITION); ::AppendMenu(hNewMenu,MF_OWNERDRAW | MF_BYCOMMAND | uState,uID,(LPCTSTR)pMenuItem); //pNewMenu->AppendMenuEx(MF_STRING,uID,strText); } } } BOOL CMenuEx::ModifyMenuEx(UINT nPosition, UINT nFlags, UINT nIDNewItem, LPCTSTR lpszNewItem) { UINT uItemID = 0; if(nFlags & MF_BYPOSITION) { uItemID = GetMenuItemID((int)nPosition); } else { uItemID = nPosition; } //普通菜单项和弹出式菜单 MENUITEM *pMenuItem = NULL; for(int i = 0; i < m_MenuItemArr.GetSize(); i++) { pMenuItem = m_MenuItemArr.GetAt(i); if(pMenuItem->uID == uItemID) { pMenuItem->strText = lpszNewItem; if((int)nIDNewItem != 0) pMenuItem->uID = nIDNewItem; break; } } //没找到对应的菜单项 if(i >= m_MenuItemArr.GetSize()) { MENUITEM *pMenuItem = new MENUITEM; pMenuItem->strText = lpszNewItem; pMenuItem->uID = nIDNewItem; pMenuItem->pImageList = &m_ImageList; m_MenuItemArr.Add(pMenuItem); } nFlags &= ~MF_STRING; nFlags |= MF_OWNERDRAW; return CMenu::ModifyMenu(nPosition,nFlags,nIDNewItem,(LPCTSTR)pMenuItem); } int CMenuEx::CalculateLeftImagePos(CMenu *pPopupMenu) { int MenuItemCount = pPopupMenu->GetMenuItemCount(); for(int i = 0 ; i < MenuItemCount; i++) { int nID = (int) pPopupMenu->GetMenuItemID(i); //TRACE1( "/n#Calc# nID = %d",nID ); CString strText; pPopupMenu->GetMenuString(i,strText,MF_BYPOSITION); for(int j = 0; j < m_MenuItemArr.GetSize(); j++) { MENUITEM *pMenuItem = m_MenuItemArr.GetAt(j); if((int)pMenuItem->uID == nID) { pMenuItem->uPositionImageLeft = MenuItemCount - 1 - i; //TRACE1( "/t/tPOS = %d", pMenuItem->uPositionImageLeft ); //return pMenuItem->uPositionImageLeft; } } } return -1; } // 设置选中边框颜色 void CMenuEx::SetCurSelBorderColor( COLORREF crBorder ) { m_crCurSelBorder = crBorder; CMenuEx *pSubMenu = NULL; for(int i = 0; i < m_SubMenuArr.GetSize(); i++) { pSubMenu = m_SubMenuArr.GetAt( i ); pSubMenu->SetCurSelBorderColor(crBorder); } } // 设置选中边框填充色 void CMenuEx::SetCurSelRectColor(COLORREF crFill) { m_crCurSelRect = crFill; CMenuEx *pSubMenu = NULL; for(int i = 0; i < m_SubMenuArr.GetSize(); i++) { pSubMenu = m_SubMenuArr.GetAt( i ); pSubMenu->SetCurSelRectColor(crFill); } } CMenuEx* CMenuEx::GetSubMenu( int nPos ) const { return (CMenuEx*)CMenu::GetSubMenu( nPos ); } // 设置左边竖直矩形的边框颜色 void CMenuEx::SetLeftRectBkColor(COLORREF crBkgnd) { m_crLeftErectRect = crBkgnd; CMenuEx *pSubMenu = NULL; for(int i = 0; i < m_SubMenuArr.GetSize(); i++) { pSubMenu = m_SubMenuArr.GetAt( i ); pSubMenu->SetLeftRectBkColor( crBkgnd ); } } void CMenuEx::SetCheckBmp(UINT nBmpID) { nCheckBmpID = nBmpID; CMenuEx *pSubMenu = NULL; for(int i = 0; i < m_SubMenuArr.GetSize(); i++) { pSubMenu = m_SubMenuArr.GetAt( i ); pSubMenu->SetCheckBmp( nBmpID ); } } // 设置菜单项的位图 void CMenuEx::SetMenuItemImage(UINT nMenuID, UINT nBmpSourceID) { m_nMenuID = nMenuID ; //TRACE1( "/nnPos = %d", nPos ); CMenuEx *pSubMenu = NULL; for(int i = 0; i < m_SubMenuArr.GetSize(); i++) { pSubMenu = m_SubMenuArr.GetAt( i ); pSubMenu->SetMenuItemImage( nMenuID, nBmpSourceID ); } }