?? menuex.cpp
字號:
// MenuEx.cpp: implementation of the CMenuEx class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "MenuEx.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CMenuEx::CMenuEx():m_szImage(16,15)
{
m_colMenu =::GetSysColor(COLOR_MENU);
m_colText =::GetSysColor(COLOR_MENUTEXT);
m_colTextSelected =::GetSysColor(COLOR_HIGHLIGHTTEXT);
m_bInitial =FALSE;
m_bHasImageLeft =FALSE;
m_nSeparator = 10; //sparator的默認高度
}
CMenuEx::~CMenuEx()
{
m_ImageList.DeleteImageList();
while(!m_ListMenu.IsEmpty())
delete m_ListMenu.RemoveHead();
if(m_bHasImageLeft)
m_bmpImageLeft.DeleteObject();
}
/////////////////////////////////////////////////
//當菜單項為不可用時繪制灰色的文本
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
{
if(bSelected)
{
//菜單選中
//當該項被選中僅多繪制一個立體矩形
pDC->Draw3dRect(&rt,RGB(255,255,255),RGB(127,127,127));
}
rt.InflateRect(-2,-2);
//畫出"√"
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(m_colText);
pDC->DrawText("√",&rt,DT_EXPANDTABS|DT_VCENTER|DT_SINGLELINE);
}
rect.left +=m_szImage.cx + 4 +2 ;
return ;
}
if(bHasImage)
{
CPoint pt(rt.left+2 , rt.top+2 );
UINT uStyle =ILD_TRANSPARENT; //CImageList::Draw()繪制位圖的風格
if(bGrayed)
{
uStyle |=ILD_BLEND50; //菜單不可用所以位圖較暗
}
else
{
if(bSelected)
{
//當該項被選中僅多繪制一個立體矩形
pDC->Draw3dRect(&rt,RGB(255,255,255),RGB(127,127,127));
}
}
m_ImageList.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 rtText,BOOL bSelected, BOOL bGrayed, LPMENUITEM lpItem)
{
//選中狀態的菜單項要先畫出立體矩形
if(bSelected)
pDC->Draw3dRect(&rect,RGB(127,127,127),RGB(255,255,255));
if(bGrayed)
{
GrayString(pDC,lpItem->strText,rtText);
}
else
{
pDC->DrawText(lpItem->strText,rtText,DT_LEFT|DT_EXPANDTABS|DT_VCENTER);
}
}
void CMenuEx::DrawImageLeft(CDC *pDC, CRect &rect,LPMENUITEM lpItem)
{
if(!m_bHasImageLeft || lpItem->uPositionImageLeft ==-1)
return ;
CDC memDC;
memDC.CreateCompatibleDC(pDC);
CBitmap *oldBmp =(CBitmap *) memDC.SelectObject(&m_bmpImageLeft);
int cy; //設定該菜單項應從哪畫起
if(m_szImageLeft.cy >= lpItem->uPositionImageLeft + rect.Height())
{
cy =(int) m_szImageLeft.cy - lpItem->uPositionImageLeft - rect.Height();
ASSERT(cy>=0);
}
else
cy =0;
pDC->BitBlt(rect.left ,rect.top ,m_szImageLeft.cx ,rect.Height(),&memDC,0,cy,SRCCOPY);
memDC.SelectObject(oldBmp);
memDC.DeleteDC();
rect.left +=m_szImageLeft.cx+1;
}
void CMenuEx::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
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);
//設定顯示模式
dc.SetBkMode(TRANSPARENT);
//繪制側邊位圖
DrawImageLeft(&dc,rect,lpItem);
if(lpItem->uID==0)//分隔條
{
rect.top =rect.Height()/2+rect.top ;
rect.bottom =rect.top +2;
rect.left +=2;
rect.right -=2;
dc.Draw3dRect(rect,RGB(64,0,128),RGB(255,255,255));
}
else
{
BOOL bSelected =lpDIS->itemState & ODS_SELECTED;
BOOL bChecked =lpDIS->itemState & ODS_CHECKED;
BOOL bGrayed =lpDIS->itemState & ODS_GRAYED;
BOOL bHasImage =(lpItem->uIndex!=-1);
//設定菜單文本的區域
CRect rtText(rect.left+m_szImage.cx+4+2, rect.top,rect.right ,rect.bottom );
rtText.InflateRect(-2,-2);
//繪制菜單位圖
DrawMenuItemImage(&dc,rect,bSelected,bChecked,bGrayed,bHasImage,lpItem);
//繪制菜單文本
TextMenu(&dc,rect,rtText,bSelected,bGrayed,lpItem);
#ifdef MENUCHAR
//加入當前菜單鏈表
m_currentListMenu.AddTail(lpItem);
#endif
}
dc.Detach();
}
//////////////////////////////////////////////////////////
//改變菜單風格
//注意第二個參數:FALSE:表示pMenu指向的不是第一級菜單
void CMenuEx::ChangeStyle(CMenu *pMenu,CToolBar *pToolBar,BOOL bIsMainMenu)
{
ASSERT(pMenu);
TRACE("ChangeStyle\n");//AfxMessageBox("");
LPMENUITEM lpItem;
CMenu *pSubMenu;
int m,nPosition=0; //該變量用來繪制側邊位圖的位置
int inx;
UINT idx,x;
for(int i=(int)pMenu->GetMenuItemCount()-1 ;i>=0; i--)
{
lpItem =new MENUITEM;
lpItem->uID =pMenu->GetMenuItemID(i);
if(!bIsMainMenu) //不是第一級菜單
lpItem->uPositionImageLeft =-1;//二級以下菜單不支持側邊位圖
else
lpItem->uPositionImageLeft =nPosition;
if(lpItem->uID >0)
{
if(bIsMainMenu)
nPosition +=m_szImage.cy+4;
//保存菜單文本
pMenu->GetMenuString(i,lpItem->strText,MF_BYPOSITION);
#ifdef MENUCHAR
//保存菜單文本中&后的字符
//如果沒有則lpItem->uChr為0
int ret=lpItem->strText.Find('&');
lpItem->uChr =0;
if(ret>=0)
lpItem->uChr =lpItem->strText[ret+1];
//字符統一成大小
lpItem->uChr &=~0x20;
#endif
//由工具欄位圖中尋找菜單項的位圖
//如果沒有則uIndex為-1
lpItem->uIndex =-1;
if(pToolBar)
{
for(m=0; m<(pToolBar->GetToolBarCtrl().GetButtonCount()) ;m++)
{
pToolBar->GetButtonInfo(m,idx,x,inx);
if(idx==lpItem->uID)
{
lpItem->uIndex=inx;
break;
}
}
}
//如果該項下還有子菜單,則遞歸調用該函數來修改其子菜單的風格
pSubMenu =pMenu->GetSubMenu(i);
if(pSubMenu)
ChangeStyle(pSubMenu,pToolBar);
}
else
{
if(bIsMainMenu)
nPosition +=m_nSeparator;
}
//修改菜單風格為自繪
pMenu->ModifyMenu(i,MF_BYPOSITION|MF_OWNERDRAW,lpItem->uID,(LPCTSTR)lpItem);
m_ListMenu.AddTail(lpItem);
}
}
//////////////////////////////////////////////////////////
//由工具欄的位圖來產生菜單所用的位圖列表m_ImageList
int CMenuEx::GetImageFromToolBar(UINT uToolBar, CToolBar *pToolBar,COLORREF crMask/*工具欄位圖的掩碼*/)
{
if(!pToolBar)
return 0;
CBitmap bmp;
int nWidth,nHeight;
BITMAP bmpInfo;
bmp.LoadBitmap(uToolBar);
bmp.GetBitmap(&bmpInfo);
//得到位圖的高度
nHeight =bmpInfo.bmHeight;
int nCount=0;
int ret =pToolBar->GetToolBarCtrl().GetButtonCount();
//得到工具欄中位圖的個數nCount
for(int i=0;i<ret;i++)
if(pToolBar->GetItemID(i)!=ID_SEPARATOR)
nCount ++;
//計算出位圖的寬度
nWidth =bmpInfo.bmWidth/nCount;
bmp.DeleteObject();
TRACE("Menu Bitmap--width:%d\theight:%d\n",nWidth,nHeight);
//創建位圖列表
m_ImageList.Create(uToolBar,nWidth,nHeight,crMask);
m_szImage.cx =nWidth;
m_szImage.cy =nHeight;
return nCount;
}
void CMenuEx::InitMenu(CMenu *pMenu, UINT uToolBar, CToolBar *pToolBar)
{
//已設定了風格
if(m_bInitial)
return ;
GetImageFromToolBar(uToolBar,pToolBar);
CMenu *pSubMenu,*pSubsub;
MENUITEM *lpItem;
UINT i;
int j,m;
int nPosition; //該變量用來繪制側邊位圖的位置
for(i=0;i<pMenu->GetMenuItemCount();i++)
{
pSubMenu =pMenu->GetSubMenu(i);
if(pSubMenu)
{
nPosition =0;
//注意j一定要為int類型,如果為UINT是檢查不出j>=0!
for(j=(int)pSubMenu->GetMenuItemCount()-1;j>=0;j--)
{
lpItem =new MENUITEM;
lpItem->uID =pSubMenu->GetMenuItemID(j);
lpItem->uPositionImageLeft =nPosition;
if(lpItem->uID>0)
{
nPosition +=m_szImage.cy+4;
pSubMenu->GetMenuString(j,lpItem->strText,MF_BYPOSITION);
#ifdef MENUCHAR
//保存菜單文本中&后的字符
//如果沒有則lpItem->uChr為0
int ret =lpItem->strText.Find('&');
lpItem->uChr=0;
if(ret>=0)
lpItem->uChr =lpItem->strText[ret+1];
//統一大小
lpItem->uChr &=~0x20;
#endif
//由工具欄位圖中尋找菜單項的位圖
//如果沒有則uIndex為-1
lpItem->uIndex =-1;
for(m=0; m<(pToolBar->GetToolBarCtrl().GetButtonCount()) ;m++)
{
int inx;
UINT idx,x;
pToolBar->GetButtonInfo(m,idx,x,inx);
if(idx==lpItem->uID)
{
lpItem->uIndex=inx;
break;
}
}
}
else
{
//separator
nPosition +=m_nSeparator;
}
m_ListMenu.AddTail(lpItem);
pSubMenu->ModifyMenu(j,MF_BYPOSITION|MF_OWNERDRAW,
lpItem->uID,LPCTSTR(lpItem));
pSubsub =pSubMenu->GetSubMenu(j);
//只有第一級菜單才由工具欄獲得位圖!!
if(pSubsub)
ChangeStyle(pSubsub,pToolBar);
}
}
}
m_bInitial =TRUE;
}
void CMenuEx::MeasureItem(LPMEASUREITEMSTRUCT lpMIS)
{
MENUITEM *lpItem =(LPMENUITEM)lpMIS->itemData;
if(lpItem->uID==0)//分隔條
{
lpMIS->itemHeight =m_nSeparator;
//lpMIS->itemWidth =50;
}
else
{
CDC *pDC =AfxGetMainWnd()->GetDC();
CString strText=lpItem->strText;
CSize size;
size=pDC->GetTextExtent(lpItem->strText);
lpMIS->itemWidth = size.cx +m_szImage.cx+4;
lpMIS->itemHeight =m_szImage.cy+4;
AfxGetMainWnd()->ReleaseDC(pDC);
}
}
void CMenuEx::SetImageLeft(UINT idBmpLeft)
{
m_bmpImageLeft.LoadBitmap(idBmpLeft);
m_bHasImageLeft = TRUE;
BITMAP bmpInfo;
m_bmpImageLeft.GetBitmap(&bmpInfo);
m_szImageLeft.cx =bmpInfo.bmWidth;
m_szImageLeft.cy =bmpInfo.bmHeight;
}
#ifdef MENUCHAR
LRESULT CMenuEx::MenuChar(UINT nChar)
{
nChar &=~0x20;
MENUITEM *lpItem;
for(POSITION pos=m_currentListMenu.GetHeadPosition();pos;)
{
lpItem =(LPMENUITEM)m_currentListMenu.GetNext(pos);
if(lpItem->uChr ==nChar)
{
AfxGetMainWnd()->SendMessage(WM_COMMAND,lpItem->uID);
return 1L;
}
}
return 0L;
}
#endif
void CMenuEx::SetTextColor(COLORREF crColor)
{
m_colText =crColor;
}
void CMenuEx::SetBackColor(COLORREF crColor)
{
m_colMenu =crColor;
}
void CMenuEx::SetHighLightColor(COLORREF crColor)
{
m_colTextSelected =crColor;
}
//////////////////////////////////////////////////////
//修改菜單的風格
//與InitMenu不同的是:InitMenu并不修改第一級菜單為自繪風格,而
//該函數有包括第一級菜單
//但必須注意:該類的任一實例都只能調用這兩個函數中的一個,不能一同使用
void CMenuEx::InitPopupMenu(CMenu *pPopupMenu,UINT uToolBar, CToolBar *pToolBar)
{
//已設定了主窗口菜單風格
if(m_bInitial)
return ;
GetImageFromToolBar(uToolBar,pToolBar);
ChangeStyle(pPopupMenu,pToolBar);
m_bInitial =TRUE;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -