会员: 密码:  免费注册 | 忘记密码 | 会员登录 网页功能: 加入收藏 设为首页 网站搜索  
技术文档 > VC文档 > MFC应用
自绘菜单的实现
发表日期:2002-12-08 00:00:00作者: 出处:  

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

  1. 设置字体颜色。
  2. 设置高亮度颜色。
  3. 设置高亮度时的风格。
  4. 设置选中时和在普通状态下的菜单显示的图标。
  5. 设置显示图标大小。

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 "CustomMenu.h"

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

///////////////////////////////////////////////////////////////////////////
//
// CCustomMenu

CCustomMenu::CCustomMenu()
{
	m_clrText =  GetSysColor (COLOR_MENUTEXT);
	m_clrBack = GetSysColor (COLOR_MENU);
	m_brBackground.CreateSolidBrush (m_clrBack);
	m_penBack.CreatePen (PS_SOLID,0,m_clrBack);
	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 hIcon;
	COLORREF crText = m_crText;
	// draw the colored rectangle portion
	rect.CopyRect(&lpDIS->rcItem);

	// 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)
			hIcon = NULL;
		else if (state & ODS_SELECTED)
		{
			if ((((MENUDATA *)(lpDIS->itemData))->menuIconSelected) != -1)
				hIcon = AfxGetApp ()->LoadIcon (((MENUDATA *)(lpDIS->itemData))->menuIconSelected);
			else
				hIcon = AfxGetApp()->LoadIcon (((MENUDATA*)(lpDIS->itemData))->menuIconNormal);
		}
		else
			hIcon = AfxGetApp()->LoadIcon (((MENUDATA*)(lpDIS->itemData))->menuIconNormal);

		TRACE1 ("Draw for %s\n", strText);
	}
	else
	{
		strText.Empty();
		hIcon = 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
		if (m_hilightStyle != Normal)
		{
			pDC->FillRect (rect,&m_brBackground);
		}
		else
		{
			pDC->FillRect (rect,&m_brSelect);
		}

		pDC->SelectObject (pOldPen);
		pDC->Draw3dRect (rect,GetSysColor (COLOR_3DHILIGHT),GetSysColor(COLOR_3DSHADOW));
		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");
	}
	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");
	}

	// draw the text if there is any
	//We have to paint the text only if the image is nonexistant
	if (hIcon != NULL)
	{
		if(DrawIconEx (pDC->GetSafeHdc(),rect.left,rect.top,hIcon,
			(m_iconX)?m_iconX:32,(m_iconY)?m_iconY:32,0,NULL,DI_NORMAL))
			TRACE0("Wrote the icon successfully\n");
		else
			TRACE0 ("SORRY.NOGO\n");
	}
	//This is needed always so that we can have the space for check marks
	rect.left = rect.left +((m_iconX)?m_iconX:32); 

	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 );
		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;
}
//*************************************************************************
返回顶部】 【打印本页】 【关闭窗口

关于我们 / 给我留言 / 版权举报 / 意见建议 / 网站编程QQ群   
Copyright ©2003- 2024 Lihuasoft.net webmaster(at)lihuasoft.net 加载时间 0.00408