zoukankan      html  css  js  c++  java
  • 设置菜单条及菜单项背景色(转)

    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--%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--%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; 
    } 
    
    
  • 相关阅读:
    模拟两位选手进行n羽毛球比赛(15分赛制)并计算模拟胜率
    Pyton实例
    Python图片处理
    jieba库的使用和好玩的词云
    Python汉诺塔问题
    多线程同时操作一个epoll_fd
    Linux tr命令
    iptables 深入分析
    Linux xtables
    Linux IPC 共享内存
  • 原文地址:https://www.cnblogs.com/Daywei/p/1966891.html
Copyright © 2011-2022 走看看