自绘菜单

原创 2007年10月13日 17:13:00



 


在这里提供一个C++类(CCustomMenu),该类是CMenu的子类,并且拥有自绘能力。它可以向你提供以下的功能:

设置字体颜色。
设置高亮度颜色。
设置高亮度时的风格。
设置选中时和在普通状态下的菜单显示的图标。
设置显示图标大小。
在CCustomMenu中定义了结构MENUDATA,你必须根据你的需要填充该结构,并且在增加菜单时提供该结构的指针(调用AppendMenu,InsertMenu)。下面是一个例子:

1、定义CCustomMenu的实例,和MENUDATA结构变量。

    CCustomMenu m_cCustomMenu;
    MENUDATA menuData [8]; // as many menu items are present , You should be able to use
                //new and do the same
2、调用CreateMenu()设置有关参数。
    m_customMenu.CreateMenu ();
    m_customMenu.SetIconSize (25,25); //This is to set the size of the Icon.
                        // This should be used only once for any menu
    // in order to resize it, destroy and create the menu again with different size.
    m_customMenu.SetHighlightStyle (Normal); //Or TextOnly, if you want the
    // background color to remain the same
    // and the Text color to change to the Highlight color.
        // The following setXXXColor sets the menu colors. If you dont want to change any, Dont call these member functions.
     m_customMenu.SetTextColor (RGB (255,0,0));
     m_customMenu.SetBackColor (RGB (255,255,255));
     m_customMenu.SetHighlightColor (RGB (0,0,255));
3、设置MENUDATA变量,并增加菜单项。
     lstrcpy (menuData[0].menuText , "text1");
     menuData[0].menuIconNormal= IDI_ICON1;
     m_customMenu.AppendMenu (MF_OWNERDRAW,3,(LPCTSTR)menuData);

3、在你的窗口中重载OnMeasureItem(...)函数。
void CMyView::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
    if ( lpMeasureItemStruct->CtlType == ODT_MENU &&
            IsMenu((HMENU)lpMeasureItemStruct->itemID) &&
            (lpMeasureItemStruct->itemID == (UINT)m_hMenuSub) )
    {
        m_customMenu.MeasureItem (lpMeasureItemStruct);
    }
    else
        // let MFC´s self-drawing handle it
        CView::OnMeasureItem(nIDCtl, lpMeasureItemStruct);
}

下面的函数将帮助你设置菜单属性。

    void SetTextColor (COLORREF );
    void SetBackColor (COLORREF);
    void SetHighlightColor (COLORREF);
    void SetIconSize (int, int);
    void SetHighlightStyle (HIGHLIGHTSTYLE ); // HIGHLIGHTSTYLE : enum {Normal, TextOnly}
    void SetHighlightTextColor (COLORREF);



下面是文件代码:
//*************************************************************************
// CustomMenu.h : header file
//

#if
!defined(AFX_CUSTOMMENU_H__FE5B01C3_1E02_11D1_B87A_0060979CDF6D__INCLUDED_)
#define AFX_CUSTOMMENU_H__FE5B01C3_1E02_11D1_B87A_0060979CDF6D__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
class MENUDATA
{
public:
    MENUDATA () { menuIconNormal = -1; menuIconSelected = -1;};
    char menuText[32];
    UINT menuIconNormal;
    UINT menuIconSelected;
};


typedef enum {Normal,TextOnly} HIGHLIGHTSTYLE;

////////////////////////////////////////////////
//
// CCustomMenu window

class CCustomMenu : public CMenu
{
// Construction
public:
    CCustomMenu();

// Attributes
public:

// Operations
public:

// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CCustomMenu)
    //}}AFX_VIRTUAL

// Implementation
public:
    virtual ~CCustomMenu();
    virtual void DrawItem( LPDRAWITEMSTRUCT);
    virtual void MeasureItem( LPMEASUREITEMSTRUCT );
    void SetTextColor (COLORREF );
    void SetBackColor (COLORREF);
    void SetHighlightColor (COLORREF);
    void SetIconSize (int, int);
    void SetHighlightStyle (HIGHLIGHTSTYLE );
    void SetHighlightTextColor (COLORREF);

    // Generated message map functions
protected:
    COLORREF m_crText;
    COLORREF m_clrBack;
    COLORREF m_clrText;
    COLORREF m_clrHilight;
    COLORREF m_clrHilightText;
    LOGFONT m_lf;
    CFont m_fontMenu;
    UINT m_iMenuHeight;
    BOOL m_bLBtnDown;
    CBrush m_brBackground,m_brSelect;
    CPen m_penBack;
    int m_iconX,m_iconY;
    HIGHLIGHTSTYLE m_hilightStyle;

    //{{AFX_MSG(CCustomMenu)
        // NOTE - the ClassWizard will add and remove member functions here.
    //}}AFX_MSG
};

///////////////////////////////////////
//

//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.

#endif //!defined(AFX_CUSTOMMENU_H__FE5B01C3_1E02_11D1_B87A_0060979CDF6D__INCLUDED_)

//*************************************************************************
// CustomMenu.cpp : implementation file
//

#include "stdafx.h"
#include "testdll.h"
#include "CustomMenu.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CCustomMenu::CCustomMenu()
{
    m_clrText = GetSysColor (COLOR_MENUTEXT);
    m_clrBack = GetSysColor (COLOR_MENU);

    m_brBackground.CreateSolidBrush (m_clrBack);
    m_penBack.CreatePen (PS_SOLID,1,RGB(0,0,255));
    m_crText = m_clrText;
    m_bLBtnDown = FALSE;
    m_iconX = GetSystemMetrics ( SM_CXMENUCHECK);
    m_iconY = GetSystemMetrics (SM_CYMENUCHECK );

    m_clrHilight = GetSysColor (COLOR_HIGHLIGHT);
    m_brSelect.CreateSolidBrush (m_clrHilight);
    m_clrHilightText = GetSysColor (COLOR_HIGHLIGHTTEXT);

    ZeroMemory ((PVOID) &m_lf,sizeof (LOGFONT));
    NONCLIENTMETRICS nm;
    nm.cbSize = sizeof (NONCLIENTMETRICS);

    //Get the system metrics for the Captionfromhere
    VERIFY (SystemParametersInfo (SPI_GETNONCLIENTMETRICS,0,&nm,0));

    m_lf = nm.lfMenuFont;
    m_iMenuHeight = nm.iMenuHeight;
    m_fontMenu.CreateFontIndirect (&m_lf);
}

CCustomMenu::~CCustomMenu()
{
    if ((HBRUSH) m_brBackground != NULL)
        m_brBackground.DeleteObject ();
    if ((HFONT)m_fontMenu !=NULL)
        m_fontMenu.DeleteObject ();
    if ((HBRUSH)m_brSelect != NULL)
         m_brSelect.DeleteObject ();
}

 

////////////////////////////////////////////////
//
// CCustomMenu message handlers


void CCustomMenu::DrawItem (LPDRAWITEMSTRUCT lpDIS)
{
    ASSERT(lpDIS != NULL);

    CDC* pDC = CDC::FromHandle(lpDIS->hDC);
    CRect rect;
    HICON hNormalIcon;
 HICON hLightIcon;
    COLORREF crText = m_crText;
    // draw the colored rectangle portion

    rect.CopyRect(&lpDIS->rcItem);

 CRect originRect;
 originRect.CopyRect(&lpDIS->rcItem);
 //rect.left=rect.left+3;
 //rect.top=rect.top+3;
    // draw the up/down/focused/disabled state

    UINT action = lpDIS->itemAction;
    UINT state = lpDIS->itemState;
    CString strText;
    LOGFONT lf;
    lf = m_lf;

    CFont dispFont;
    CFont *pFont;
    //GetWindowText(strText);
    if (lpDIS->itemData != NULL)
    {
        strText = (((MENUDATA*) (lpDIS->itemData))->menuText);
        if ((((MENUDATA *)(lpDIS->itemData))->menuIconNormal) == -1)
  {  
   hNormalIcon = NULL;
   hLightIcon=NULL;
  }
        else if (state & ODS_SELECTED)
        {
            if ((((MENUDATA *)(lpDIS->itemData))->menuIconSelected) != -1)
   {
                hNormalIcon = AfxGetApp ()->LoadIcon (((MENUDATA *)(lpDIS->itemData))->menuIconSelected);
    hLightIcon=AfxGetApp ()->LoadIcon (((MENUDATA *)(lpDIS->itemData))->menuIconSelected);
   }
   else
   {
                hNormalIcon = AfxGetApp()->LoadIcon (((MENUDATA*)(lpDIS->itemData))->menuIconNormal);
    hLightIcon=AfxGetApp()->LoadIcon (((MENUDATA*)(lpDIS->itemData))->menuIconSelected);
   }
  }
        else
  {
            hNormalIcon = AfxGetApp()->LoadIcon (((MENUDATA*)(lpDIS->itemData))->menuIconNormal);
   hLightIcon =AfxGetApp()->LoadIcon (((MENUDATA*)(lpDIS->itemData))->menuIconSelected);
   TRACE1 ("Draw for %s/n", strText);
  }
    }
    else
    {
        strText.Empty();
        hNormalIcon = NULL;
  hLightIcon=NULL;
    }

    if ( (state & ODS_SELECTED) )
    {
        // draw the down edges

        CPen *pOldPen = pDC->SelectObject (&m_penBack);

  
        //You need only Text highlight and thats what you get
  //originRect.left=originRect.left+3;
  //originRect.top=originRect.top+3;
  //originRect.right=originRect.right-2;
  //originRect.bottom=originRect.bottom-2;

  
        if (m_hilightStyle != Normal)
        {
            pDC->FillRect (rect,&m_brBackground);//brnull
        }
        else
        {
            pDC->FillRect (rect,&m_brSelect);//brnull
        }

  pDC->Draw3dRect (rect,GetSysColor (COLOR_3DHILIGHT),GetSysColor(COLOR_3DSHADOW));
  CBrush *brnull=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
  pDC->SelectObject(brnull);
        pDC->Rectangle(originRect);
       
        pDC->SelectObject (pOldPen);
  lf.lfWeight = FW_BOLD;
        if ((HFONT)dispFont != NULL)
            dispFont.DeleteObject ();
        dispFont.CreateFontIndirect (&lf);
        crText = m_clrHilightText;

        //While selected move the text a bit
        TRACE0 ("SELECT,SELECTED/n");
        if(DrawIconEx (pDC->GetSafeHdc(),rect.left,rect.top,hLightIcon,
            (m_iconX)?m_iconX:32,(m_iconY)?m_iconY:32,0,NULL,DI_NORMAL))//m_brSelectm_brBackground
            TRACE0("Wrote the icon successfully/n");
 }
    else
    {
        CPen *pOldPen = pDC->SelectObject (&m_penBack);
        pDC->FillRect (rect,&m_brBackground);
        pDC->SelectObject (pOldPen);
        // draw the up edges
        pDC->Draw3dRect (rect,m_clrBack,m_clrBack);
        if ((HFONT)dispFont != NULL)
            dispFont.DeleteObject ();
        dispFont.CreateFontIndirect (&lf); //Normal

        TRACE0 ("SELECT, NORMAL/n");
        if(DrawIconEx (pDC->GetSafeHdc(),rect.left,rect.top,hNormalIcon,
            (m_iconX)?m_iconX:32,(m_iconY)?m_iconY:32,0,NULL,DI_NORMAL))//m_brSelectm_brBackground
            TRACE0("Wrote the icon successfully/n");  
 }
 /*
    if ((hNormalIcon != NULL) && (state & ODS_SELECTED))
    {
        if(DrawIconEx (pDC->GetSafeHdc(),rect.left,rect.top,hNormalIcon,
            (m_iconX)?m_iconX:32,(m_iconY)?m_iconY:32,0,NULL,DI_NORMAL))//m_brSelectm_brBackground
            TRACE0("Wrote the icon successfully/n");
        else
            TRACE0 ("SORRY.NOGO/n");
    }

 else
 {
        if(DrawIconEx (pDC->GetSafeHdc(),rect.left,rect.top,hLightIcon,
            (m_iconX)?m_iconX:32,(m_iconY)?m_iconY:32,0,NULL,DI_NORMAL))//m_brSelectm_brBackground
            TRACE0("Wrote the icon successfully/n");
        else
            TRACE0 ("SORRY.NOGO/n");
 }
 */
    // draw the text if there is any
    //We have to paint the text only if the image is nonexistant

    //This is needed always so that we can have the space for check marks
 
    rect.left = rect.left +((m_iconX)?m_iconX:32)+5;
 
    if ( !strText.IsEmpty())
    {
        // pFont->GetLogFont (&lf);

        int iOldMode = pDC->GetBkMode();

        pDC->SetBkMode( TRANSPARENT);

        pDC->SetTextColor( crText);

        pFont = pDC->SelectObject (&dispFont);
        TRACE1( "About To DrawText %s/n",strText);
        pDC->DrawText (strText,rect,DT_LEFT|DT_SINGLELINE|DT_VCENTER);
        TRACE0("Done/n");
        pDC->SetBkMode( iOldMode );
  

  //CBrush *brnull=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
  //pDC->FillRect(&originRect,brnull);
        pDC->SelectObject (pFont); //set it to the old font
    }

 

    dispFont.DeleteObject ();
}

void CCustomMenu::MeasureItem( LPMEASUREITEMSTRUCT lpMIS )
{
    CDC *pDC = AfxGetApp()->m_pMainWnd->GetDC();
    CFont* pFont = pDC->SelectObject (&m_fontMenu);
    int iconX = 0,iconY= 0;
    TEXTMETRIC tm;
    pDC->GetTextMetrics (&tm);
    pDC->SelectObject (pFont);
    AfxGetApp()->m_pMainWnd->ReleaseDC (pDC);

    if (m_iconX)
        iconX = m_iconX;
    if (m_iconY)
        iconY = m_iconY;

    lpMIS->itemWidth = iconX + tm.tmAveCharWidth * lstrlen(((MENUDATA*)(lpMIS->itemData))->menuText) +10;
    lpMIS->itemHeight = (iconY > (m_iMenuHeight+1))?iconY:m_iMenuHeight + 1;
}

void CCustomMenu::SetIconSize (int width, int height)
{
    m_iconX = width;
    m_iconY = height;
}

void CCustomMenu::SetTextColor (COLORREF clrText)
{
    m_crText = clrText;
}

void CCustomMenu::SetBackColor (COLORREF clrBack)
{
    m_clrBack = clrBack;
    if ((HBRUSH)m_brBackground != NULL)
        m_brBackground.DeleteObject ();
    m_brBackground.CreateSolidBrush (clrBack);
}

void CCustomMenu::SetHighlightColor (COLORREF clrHilight)
{
    m_clrHilight = clrHilight;
    if ((HBRUSH)m_brSelect != NULL)
            m_brSelect.DeleteObject ();
    m_brSelect.CreateSolidBrush (clrHilight);
}

void CCustomMenu::SetHighlightTextColor (COLORREF clrHilightText)
{
    m_clrHilightText = clrHilightText;
}


void CCustomMenu::SetHighlightStyle (HIGHLIGHTSTYLE hilightStyle)
{
    m_hilightStyle = hilightStyle;
}
 

// CustomMenu.cpp: implementation of the CCustomMenu class.
//
//////////////////////////////////////////////////////////////////////

菜单自绘方面的知识

1要实现漂亮的界面菜单,必须要启动菜单项的自绘功能,所谓菜单的自绘,就是让菜单自己管理自己的显示效果,为此,首先要作的就是设置菜单项的风格为MF_OWNERDRAW(自绘制),设置菜单的自绘功能即可以...
  • ponydph
  • ponydph
  • 2006-12-28 10:06:00
  • 4471

MFC 实现自绘菜单

//首次查找msdn,CMenu的OverridablesDrawItemCalled by the framework when a visual aspect of an owner-drawn ...
  • yyyzlf
  • yyyzlf
  • 2009-09-21 23:23:00
  • 4804

VC++完美实现精美自绘菜单

  • 2011年05月04日 22:47
  • 224KB
  • 下载

windows界面编程之自绘菜单

#include LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE h...
  • u014660247
  • u014660247
  • 2016-04-18 02:16:16
  • 242

MFC 菜单自绘

背景:由于项目要求将现有MFC MDI框架的程序作一次界面优化,首要的就是系统菜单的优化。具体要求有菜单项尺寸、菜单背景色,菜单栏背景色等。工作期间深刻体会到了MFC做界面的痛苦,这里把这期间所使用到...
  • u010679316
  • u010679316
  • 2016-06-16 20:52:00
  • 2255

7.VC(ui)-无边框/有边框菜单自绘

菜单自绘分为两类,一类为无边框,一类为有边框,无边框是通过hook实现的,有边框菜单:...
  • hgy413
  • hgy413
  • 2010-12-13 20:27:00
  • 4461

VC++的菜单控制和自绘菜单。

菜单控制为什么即使调用EnableMenuItem菜单项后,菜单项还处于禁止状态  需要将CFrameWnd:: m_bAutomenuEnable设置为FALSE,如果该数据成员为TRUE(缺省值)...
  • gsky
  • gsky
  • 2007-02-01 13:13:00
  • 909

简单实现菜单自绘

简单对下面3 个消息处理 就可实现菜单自绘, 其他控件类似;   //WM_DRAWITEM:绘制菜单的样式//WM_MEASUREITEM:指定要绘制菜单的大小//WM_INITMENU:把框架菜单...
  • Blue_Dream_
  • Blue_Dream_
  • 2009-02-03 18:41:00
  • 1898

如何在Visual C#中自绘菜单

 如何在Visual C#中自绘菜单 作者:Cryingwind 下载本文示例代码 当用户点击程序的主菜单项,下拉菜单弹出时,windows会对该下拉菜单的每个菜...
  • winpassword
  • winpassword
  • 2008-08-06 09:40:00
  • 683

MFC小练手:详解自绘右键菜单(继承CMenu)

也许女生被人感觉审美观会好点,所以第一个任务就是设计一个菜单。   而我的审美观觉得我做的东西都不会很colorful,因为我是个素色主义者,平日里穿的衣服裙子都是黑白灰红的深女风。(咳跑题了) ...
  • ennika
  • ennika
  • 2015-08-21 09:09:55
  • 3330
收藏助手
不良信息举报
您举报文章:自绘菜单
举报原因:
原因补充:

(最多只允许输入30个字)