自绘菜单(CMenu)

自绘菜单(CMenu)_第1张图片

 

.CPP

#include "stdafx.h"
#include "MyMenu.h"


CMyMenu::CMyMenu()
{
	m_szItemSize.cx			=	95;
	m_szItemSize.cy			=	26;

	m_nTextSize				=	13;

	m_sResourceType			=	_T("PNG");
	m_sTextName				=	_T("宋体");

	m_crNormalItemCol		=	RGB(255,255,255);
	m_crSelectItemCol		=	RGB(226,226,226);

	m_crNormalTextCol		=	RGB(53,53,53);
	m_crSelectTextCol		=	RGB(0,0,0);

	m_crSelectImgBkCol		=	RGB(226,226,226);
	m_crNormalImgBkCol		=	RGB(255,255,255);

	m_crCheckItemCol		=	RGB(128,128,255); 
}

CMyMenu::~CMyMenu()
{
}

void CMyMenu::SetNoBorder(BOOL bBor)
{
	if (bBor)
	{
		MENUINFO menuinfo;
		menuinfo.cbSize = sizeof(MENUINFO);
		menuinfo.fMask = MIM_APPLYTOSUBMENUS | MIM_BACKGROUND;  //选择设置的类型
		menuinfo.hbrBack = CreateSolidBrush(GetNormalItemColor());  //设置菜单背景色
		SetMenuInfo(&menuinfo);
	}
}

void CMyMenu::MeasureItem(LPMEASUREITEMSTRUCT lpMS)
{
	lpMS->itemWidth = m_szItemSize.cx;//菜单项的宽度

	lpMS->itemHeight = m_map[lpMS->itemID].nHeight;//每个菜单项的高度
}

void CMyMenu::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{

	CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);

	CRect rect = lpDrawItemStruct->rcItem;

	CString strText;
	SItem &sItem = m_map[lpDrawItemStruct->itemID];

	if(lpDrawItemStruct->itemID) strText = sItem.szText;

	CRect ImgRc=rect;
	ImgRc.right=rect.left+rect.Height();
	CRect TextRc=rect;
	TextRc.left+=rect.Height();
	if((lpDrawItemStruct->itemState & ODS_SELECTED)&&(lpDrawItemStruct->itemAction & ODA_SELECT))
	{
		pDC->FillSolidRect(&TextRc,m_crSelectItemCol/*::GetSysColor(COLOR_MENU)*/);
		pDC->FillSolidRect(&ImgRc,m_crSelectImgBkCol/*::GetSysColor(COLOR_MENU)*/);
		pDC->SetTextColor(m_crSelectTextCol);	

		//CPen pen(PS_SOLID,1,GetSysColor(COLOR_HIGHLIGHT));
		////rect.DeflateRect(1,1);
		//CBrush br(RGB(182,189,210));
		//pDC->SelectObject(&pen);
		//pDC->SelectObject(br);
		//pDC->Rectangle(rect);

	}
	else if(lpDrawItemStruct->itemState & ODS_CHECKED)
	{
		pDC->FillSolidRect(&TextRc,m_crCheckItemCol/*::GetSysColor(COLOR_MENU)*/);
		pDC->FillSolidRect(&ImgRc,m_crCheckItemCol/*::GetSysColor(COLOR_MENU)*/);
		pDC->SetTextColor(m_crSelectTextCol);	
	}
	else//非选中状态:普通背景填充
	{
		pDC->FillSolidRect(&TextRc,m_crNormalItemCol/*GetSysColor(COLOR_MENU)*/);
		pDC->FillSolidRect(&ImgRc,m_crNormalImgBkCol/*::GetSysColor(COLOR_MENU)*/);
		pDC->SetTextColor(m_crNormalTextCol);

		if (rect.Height() == 3)//如果是分隔条菜单:画两条线
		{
			CPen pen1(PS_SOLID,1,GetSysColor(COLOR_BTNSHADOW));
			pDC->SelectObject(&pen1);
			pDC->MoveTo(rect.left+2,rect.top+1);
			pDC->LineTo(rect.right-2,rect.top+1);

			CPen pen2(PS_SOLID,1,GetSysColor(COLOR_HOTLIGHT));
			pDC->SelectObject(&pen2);
			pDC->MoveTo(rect.left+2,rect.top+2);
			pDC->LineTo(rect.right-2,rect.top+2);

			return;
		}
		rect.DeflateRect(1,1);

	}

	if(sItem.hImg)
	{
		loadimage(pDC,ImgRc,m_sResourceType,sItem.hImg);
	}
	CFont TextFont;
	TextFont.CreateFont(
		m_nTextSize,               // 字体的高度           
		0,                         // 字体的宽度
		0,                         // 字体显示的角度
		0,                         // 字体的角度
		FW_NORMAL,                 // 字体的磅数
		FALSE,                     // 斜体字体
		FALSE,                     // 带下划线的字体
		0,                         // 带删除线的字体
		ANSI_CHARSET,              // 所需的字符集
		OUT_DEFAULT_PRECIS,        // 输出的精度
		CLIP_DEFAULT_PRECIS,       // 裁减的精度
		DEFAULT_QUALITY,           // 逻辑字体与输出设备的实际字体之间的精度
		DEFAULT_PITCH | FF_SWISS,  // 字体间距和字体集
		m_sTextName);              // 字体名称
	CFont* pOldFont = NULL;           
	pOldFont = pDC->SelectObject(&TextFont);

	
	pDC->SetBkMode(TRANSPARENT);
	if(sItem.hImg)
	{
		rect.left+=ImgRc.Width()+10;
		pDC->DrawText(strText,rect,DT_LEFT|DT_VCENTER|DT_SINGLELINE);
	}
	else
	{
		pDC->DrawText(strText,rect,DT_CENTER|DT_VCENTER|DT_SINGLELINE);
	}

	pDC->SelectObject(pOldFont);
	TextFont.DeleteObject();
}


BOOL CMyMenu::AppendMenu(UINT nFlags,UINT_PTR nIDNewItem,LPCTSTR lpszNewItem,UINT hImg)
{
	//将菜单的文字和图标信息按照ID进行登记,以便自绘时使用
	SItem sItem = {hImg};
	if(nFlags & MF_SEPARATOR) 
	{
		sItem.nHeight = 3;
	}
	else
	{
		sItem.nHeight = m_szItemSize.cy;
#ifdef _UNICODE
		if(lpszNewItem)WideCharToMultiByte(CP_ACP, 0, lpszNewItem, -1, sItem.szText, 100, NULL, NULL);
#else
		if(lpszNewItem) strcpy(sItem.szText,lpszNewItem);
#endif
	}
	//根据ID添加到map中
	m_map[nIDNewItem] = sItem;
	//每个插入的菜单项都自动添加自绘属性
	return CMenu::AppendMenu(nFlags|MF_OWNERDRAW,nIDNewItem,lpszNewItem);

}


_inline void CMyMenu::loadimage(CDC *pDC,CRect rect,LPCTSTR lpType,UINT nResID)
{
	CImage m_Image;
	CComPtr stream;
	stream = NULL;
	// 查找资源
	HRSRC hRsrc = ::FindResource(AfxGetResourceHandle(), MAKEINTRESOURCE(nResID), lpType);
	if (hRsrc == NULL) return;

	// 加载资源
	HGLOBAL hImgData = ::LoadResource(AfxGetResourceHandle(), hRsrc);
	if (hImgData == NULL)
	{
		::FreeResource(hImgData);
		return;
	}

	// 锁定内存中的指定资源
	LPVOID lpVoid    = ::LockResource(hImgData);

	//LPSTREAM pStream = NULL;
	DWORD dwSize    = ::SizeofResource(AfxGetResourceHandle(), hRsrc);
	HGLOBAL hNew    = ::GlobalAlloc(GHND, dwSize);
	LPVOID lpByte    = (LPBYTE)::GlobalLock(hNew);
	::memcpy(lpByte, lpVoid, dwSize);

	// 解除内存中的指定资源
	::GlobalUnlock(hNew);

	// 从指定内存创建流对象
	HRESULT ht = ::CreateStreamOnHGlobal(hNew, TRUE, &stream);
	if ( ht != S_OK )
	{
		GlobalFree(hNew);
	}
	else
	{
		// 加载图片
		HRESULT ret = m_Image.Load(stream);
		if (S_OK==ret)
		{
			if (m_Image.GetBPP() == 32)
			{
				for (int i=0;i(m_Image.GetPixelAddress(i , j)); 
						pucColor[0] = pucColor[0] * pucColor[3] / 255;   
						pucColor[1] = pucColor[1] * pucColor[3] / 255;   
						pucColor[2] = pucColor[2] * pucColor[3] / 255;   
					}
				}
			}

			if(rect.Width()>m_Image.GetWidth())
			{
				rect.DeflateRect((rect.Width()-m_Image.GetWidth())/2,0);
			}
			if(rect.Height()>m_Image.GetHeight())
			{
				rect.DeflateRect(0,(rect.Height()-m_Image.GetHeight())/2);
			}
			m_Image.Draw(pDC->m_hDC,rect);
		}

		GlobalFree(hNew);
	}
	
	// 释放资源
	::FreeResource(hImgData);
}

.H

#pragma once


// CMyMenu
class CMyMenu : public CMenu
{
public:
	CMyMenu();
	virtual ~CMyMenu();
private:
	struct SItem{
		UINT hImg;
		char szText[32];
		int nHeight;
	};
	CMap m_map;//菜单Id与对应的节点信息

public:
	virtual void MeasureItem(LPMEASUREITEMSTRUCT lpMS);
	virtual void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/);
	virtual BOOL AppendMenu(UINT nFlags=0,UINT_PTR nIDNewItem=0,LPCTSTR lpszNewItem=NULL,UINT hImg=NULL);
public:
	void SetItemSize(CSize sz)				{m_szItemSize = sz;				};	//设置菜单项目尺寸
	CSize GetItemSize()						{return m_szItemSize;			};

	void SetResourceType(LPCTSTR pa)		{m_sResourceType = pa;			};	//设置图像资源类型 如BMP 支持自定义资源类型 如PNG,JPG
	LPCTSTR GetResourceType()				{return m_sResourceType;		};

	void SetSelectItemColor(COLORREF cr)	{m_crSelectItemCol = cr;		};	//设置菜单项目鼠标停留颜色
	COLORREF GetSelectItemColor()			{return m_crSelectItemCol;		};

	void SetNormalItemColor(COLORREF cr)	{m_crNormalItemCol = cr;		};	//设置菜单项目平时的颜色
	COLORREF GetNormalItemColor()			{return m_crNormalItemCol;		};

	void SetSelectTextColor(COLORREF cr)	{m_crSelectTextCol = cr;		};	//设置菜单文字鼠标停留颜色
	COLORREF GetSelectTextColor()			{return m_crSelectTextCol;		};

	void SetNomalTextColor(COLORREF cr)		{m_crNormalTextCol = cr;		};	//设置菜单文字平时颜色
	COLORREF GetNomalTextColor()			{return m_crNormalTextCol;		};

	void SetSelectImgBkColor(COLORREF cr)	{m_crSelectImgBkCol = cr;		};	//设置鼠标停留图片背景颜色
	COLORREF GetSelectImgBkColor()			{return m_crSelectImgBkCol;		};

	void SetNormalImgBkColor(COLORREF cr)	{m_crNormalImgBkCol = cr;		};	//设置平时图片背景颜色
	COLORREF GetNormalImgBkColor()			{return m_crNormalImgBkCol;		};

	void SetCheckItemColor(COLORREF cr)		{m_crCheckItemCol = cr;			};	//设置平时图片背景颜色
	COLORREF GetCheckItemColor()			{return m_crCheckItemCol;		};

	void SetTextSize(int sz)				{m_nTextSize = sz;				};	//设置文字大小
	int GetTextSize()						{return m_nTextSize;			};

	void SetTextType(LPCTSTR pa)			{m_sTextName = pa;				};	//设置字体
	LPCTSTR GetTextType()					{return m_sTextName;			};

	void SetNoBorder(BOOL bBor=FALSE);

protected:
	CSize    m_szItemSize;	
	LPCTSTR  m_sResourceType;
	int      m_nTextSize;
	LPCTSTR  m_sTextName;

	COLORREF m_crSelectItemCol;
	COLORREF m_crNormalItemCol;

	COLORREF m_crSelectTextCol;
	COLORREF m_crNormalTextCol;

	COLORREF m_crSelectImgBkCol;
	COLORREF m_crNormalImgBkCol;

	COLORREF m_crCheckItemCol;

	_inline void loadimage(CDC *pDC,CRect rect,LPCTSTR filePath,UINT nResID);
};


 

你可能感兴趣的:(C++)