设置菜单条及菜单项背景色

1、设置菜单条背景色

 

  1. // 菜单栏  
  2. m_wndMenu.LoadMenu(IDR_MAINFRAME);  
  3. SetMenu(&m_wndMenu);  
  4. // 改变菜单条背景颜色  
  5. MENUINFO   menuinfo;     
  6. menuinfo.cbSize = sizeof(MENUINFO);  
  7. menuinfo.fMask = MIM_BACKGROUND;     
  8. menuinfo.hbrBack = ::CreateSolidBrush(RGB(203, 228, 253));     
  9. CMenu*  pMenu = GetMenu();     
  10. ::SetMenuInfo(pMenu->m_hMenu, &menuinfo);     
  11. DrawMenuBar();  

2、设置菜单项背景色

重载CMenu类,重写DrawItem()方法。

网上有一个CMenuEx类,只要设置m_colMenu属性就可以了。该类可以实现Windows开始菜单风格,即菜单项可带有图标。

CMenuEx.h

    
      
#if !defined(AFX_MENUEX_H__FE677F6B_2315_11D7_8869_BB2B2A4F4D45__INCLUDED_)
#define AFX_MENUEX_H__FE677F6B_2315_11D7_8869_BB2B2A4F4D45__INCLUDED_
#include
" afxtempl.h "
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

typedef
struct tagMENUITEM
{
CString strText;
UINT uID;
#ifdef MENUCHAR
UINT uChr;
#endif
UINT uIndex;
int uPositionImageLeft;
}MENUITEM;
typedef MENUITEM
* LPMENUITEM;
////////////////////////////////////////// /
class CMenuEx : public CMenu
{
public :
void InitPopupMenu(CMenu * pPopupMenu,UINT uToolBar,CToolBar * pToolBar);
void ChangeStyle(CMenu * pMenu,CToolBar * pToolBar,BOOL bIsMainMenu = FALSE);
void SetHighLightColor(COLORREF crColor);
void SetBackColor(COLORREF);
void SetTextColor(COLORREF);
#ifdef MENUCHAR
LRESULT MenuChar(UINT nChar);
#endif
void SetImageLeft(UINT idBmpLeft);
void MeasureItem(LPMEASUREITEMSTRUCT lpMIS);
void InitMenu(CMenu * pMenu,UINT uToolBar,CToolBar * pToolBar);
void DrawItem(LPDRAWITEMSTRUCT lpDIS);
CMenuEx();
virtual ~ CMenuEx();

protected :
int m_nSeparator;
CSize m_szImageLeft;
CBitmap m_bmpImageLeft;
int m_nWidthLeftImage;
BOOL m_bHasImageLeft;
// 是否有侧边位图
BOOL m_bInitial; // 菜单是否已初始化,即设定了自绘风格
int GetImageFromToolBar(UINT uToolBar,CToolBar * pToolBar,COLORREF crMask = RGB( 192 , 192 , 192 ));
CList m_ListMenu;

#ifdef MENUCHAR
CList m_currentListMenu;
// 是m_ListMenu的子集,指当前打开的菜单
#endif

COLORREF m_colMenu;
COLORREF m_colTextSelected;
void DrawImageLeft(CDC * pDC,CRect & rect,LPMENUITEM lpItem);
void TextMenu(CDC * pDC,CRect & rect,CRect rtText,BOOL bSelected,BOOL bGrayed,LPMENUITEM lpItem);
CImageList m_ImageList;
COLORREF m_colText;
CSize m_szImage;
// 菜单项位图的大小
void DrawMenuItemImage(CDC * pDC,CRect & rect,BOOL bSelected,BOOL bChecked,BOOL bGrayed,BOOL bHasImage,LPMENUITEM lpItem);
void GrayString(CDC * pDC, const CString & str, const CRect rect);
};

CMenuEx.cpp



 

 

#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;   

}   

// 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;iGetItemID(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;iGetMenuItemCount();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; 

} 



你可能感兴趣的:(菜单)