自定义菜单

菜单

对话框的系统菜单
//预处理
#define MENU_BUTTON_ID 10246
CMenu systemMenu;
systemMenu.CreateMenu();

CMenu subPopupMenu;
subPopupMenu.CreatePopupMenu();
subPopupMenu.AppendMenu(MF_STRING, MENU_BUTTON_ID+20, _T("文字加框"));
subPopupMenu.AppendMenu(MF_STRING, MENU_BUTTON_ID+21, _T("文字替换"));
subPopupMenu.AppendMenu(MF_SEPARATOR);
subPopupMenu.AppendMenu(MF_STRING, MENU_BUTTON_ID+22, _T("文字拆分"));
subPopupMenu.AppendMenu(MF_STRING, MENU_BUTTON_ID+23, _T("文字合并"));

CMenu subPopupMenuIndex;
subPopupMenuIndex.CreatePopupMenu();
subPopupMenuIndex.AppendMenu(MF_STRING, MENU_BUTTON_ID+24, _T("文字添加前缀"));
subPopupMenuIndex.AppendMenu(MF_STRING, MENU_BUTTON_ID+25, _T("文字添加后缀"));
subPopupMenu.AppendMenu(MF_POPUP, (UINT_PTR)(&subPopupMenuIndex)->operator HMENU(), _T("文字属性"));

systemMenu.AppendMenu(MF_POPUP, (UINT_PTR)(&subPopupMenu)->operator HMENU(), _T("文字处理"));
SetMenu(&systemMenu);
资源生成菜单
CMenu systemMenu;
systemMenu.CreateMenu();
CMenu tempMenu;
tempMenu.LoadMenu(IDR_MENU_TEXT);
systemMenu.AppendMenu(MF_POPUP, (UINT_PTR)(&tempMenu)->operator HMENU(), _T("TEST"));
自定义菜单

​ 一般来说,自定义菜单比较实用,继承CMenu后,可以自定义菜单的宽度,高度,绘制各种形状等等

class CPopupMenu : public CMenu
{
public:
	CPopupMenu(void);
	~CPopupMenu(void);

public:
	void DrawTitle(CDC* pDC, CRect& rc);
	void DrawItemText(CDC* pDC, const TCHAR* itemText, UINT itemId, CRect& rc, BOOL selected = FALSE);
	void PaintVeriticalTitle(CDC* pDC, const RECT& rect, COLORREF clrFrom, COLORREF clrTo);
	virtual void CreateDrawFont();
	virtual void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/);
	virtual void MeasureItem(LPMEASUREITEMSTRUCT /*lpMeasureItemStruct*/);
    void SetTitleText(LPCTSTR titleText);
private:
	int m_totalHeight;//弹出菜单的总高度
	int m_titleWidth;//纵向标题的宽度
	CFont m_titleFont;//标题字体
	CFont m_textFont;//条目文本字体
    CString m_titleText;
};

#include "StdAfx.h"
#include "PopupMenu.h"


CPopupMenu::CPopupMenu(void)
{
	m_titleWidth = 0;
	m_totalHeight = 0;
    m_titleText = _T("");
	CreateDrawFont();
}

CPopupMenu::~CPopupMenu(void)
{
	m_textFont.DeleteObject();
	m_titleFont.DeleteObject();
	ASSERT(m_textFont.m_hObject == NULL);
	ASSERT(m_titleFont.m_hObject == NULL);
}

void CPopupMenu::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
	ASSERT(m_titleFont.m_hObject != NULL);
	ASSERT(m_textFont.m_hObject != NULL);
	CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
    const TCHAR* itemText = (const TCHAR*)lpDrawItemStruct->itemData;
    lpDrawItemStruct->rcItem.left += m_titleWidth;

	if ((lpDrawItemStruct->itemAction & ODA_DRAWENTIRE) && 
		!(lpDrawItemStruct->itemAction & ODA_SELECT))
	{
		DrawItemText(pDC, itemText, lpDrawItemStruct->itemID, CRect(lpDrawItemStruct->rcItem));
		ASSERT(lpDrawItemStruct->hwndItem);
        int itemCount = ::GetMenuItemCount((HMENU)lpDrawItemStruct->hwndItem);
        UINT firstId = ::GetMenuItemID((HMENU)lpDrawItemStruct->hwndItem, 0);
        if (lpDrawItemStruct->itemID == firstId)
        {
            if (!(lpDrawItemStruct->itemAction & ODA_SELECT))
            {
                PaintVeriticalTitle(pDC, CRect(0,0,m_titleWidth,m_totalHeight), RGB(182,215,254),RGB(18,25,154));
                DrawTitle(pDC, CRect(lpDrawItemStruct->rcItem));
            }
        }
	}
	if ((lpDrawItemStruct->itemState & ODS_SELECTED) && 
        (lpDrawItemStruct->itemAction & (ODA_SELECT|ODA_DRAWENTIRE)))
	{
        CBrush brHili;
        pDC->FillSolidRect(&lpDrawItemStruct->rcItem, ::GetSysColor(COLOR_BTNTEXT));//调整选中时的背景色
        DrawItemText(pDC, itemText, lpDrawItemStruct->itemID, CRect(lpDrawItemStruct->rcItem), TRUE);
	}

    if (!(lpDrawItemStruct->itemState & ODS_SELECTED) &&
        (lpDrawItemStruct->itemAction & ODA_SELECT))
    {
        pDC->FillSolidRect(&lpDrawItemStruct->rcItem, ::GetSysColor(COLOR_MENU));
        DrawItemText(pDC, itemText, lpDrawItemStruct->itemID, CRect(lpDrawItemStruct->rcItem));
    }
}

void CPopupMenu::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
	CDC* pDC = AfxGetApp()->m_pMainWnd->GetDC();
	ASSERT(pDC);
	ASSERT(m_textFont.m_hObject != NULL);
	CFont* oldFont = NULL;
	if (!m_titleWidth)
	{
		TEXTMETRIC textMetr;
		oldFont = pDC->SelectObject(&m_titleFont);
		ASSERT(oldFont);
		pDC->GetTextMetrics(&textMetr);
		m_titleWidth = textMetr.tmHeight + 12;
		pDC->SelectObject(oldFont);
	}

	oldFont = pDC->SelectObject(&m_textFont);
	ASSERT(oldFont);

    //绘制分隔线
    if (lpMeasureItemStruct->itemID == 0)
    {
        lpMeasureItemStruct->itemWidth -= m_titleWidth;
        lpMeasureItemStruct->itemHeight = 1;
        m_totalHeight += lpMeasureItemStruct->itemHeight;
        pDC->SelectObject(oldFont);
        AfxGetApp()->m_pMainWnd->ReleaseDC(pDC);
        return;
    }

	CSize itemSize;
	if (_tcslen((TCHAR*)lpMeasureItemStruct->itemData))
	{
		itemSize = pDC->GetTextExtent((TCHAR*)lpMeasureItemStruct->itemData,
			_tcslen((TCHAR*)lpMeasureItemStruct->itemData));
		lpMeasureItemStruct->itemWidth = itemSize.cx + m_titleWidth + 14;
		lpMeasureItemStruct->itemHeight = itemSize.cy + 10;
	}
	else
	{
		lpMeasureItemStruct->itemHeight = 12;
	}
	m_totalHeight += lpMeasureItemStruct->itemHeight;
	pDC->SelectObject(oldFont);
	AfxGetApp()->m_pMainWnd->ReleaseDC(pDC);
}

void CPopupMenu::SetTitleText(LPCTSTR titleText)
{
    if (NULL == titleText)
    {
        m_titleText = _T(" ");
    }
    else
    {
        m_titleText = titleText;
    }
}

void CPopupMenu::DrawTitle(CDC* pDC, CRect& rc)
{
    CFont* oldFont = pDC->SelectObject(&m_titleFont);
    pDC->SetTextColor(RGB(0,255,0));
    pDC->SetBkMode(TRANSPARENT);
    CSize titleSize;
    titleSize = pDC->GetTextExtent(m_titleText);
    CRect rect(0, 0, rc.left + titleSize.cx-titleSize.cy, m_totalHeight+titleSize.cy);
    pDC->DrawText(m_titleText, -1, &rect,
        DT_BOTTOM|DT_CENTER|DT_SINGLELINE);
    pDC->SelectObject(oldFont);
}

void CPopupMenu::DrawItemText(CDC* pDC, const TCHAR* itemText, UINT itemId, CRect& rc, BOOL selected)
{
    UINT itemState = GetMenuState(itemId, MF_BYCOMMAND);
    if (itemState & MF_SEPARATOR)
    {
        CRect rect(rc.left + 2, rc.top + rc.Height()/2, rc.right, rc.top + rc.Height()/2 + 2);
        pDC->Draw3dRect(&rect, ::GetSysColor(COLOR_BTNSHADOW), ::GetSysColor(COLOR_BTNHIGHLIGHT));
        return;
    }
    if (itemText == NULL || !_tcslen(itemText))
    {
        return;
    }
    pDC->SetBkMode(TRANSPARENT);
    CFont* oldFont = pDC->SelectObject(&m_textFont);
    if (itemState & MF_GRAYED)
    {
        if (!selected)
        {
            pDC->SetTextColor(RGB(255,255,255));
            pDC->DrawText(itemText, -1, &rc, DT_VCENTER|DT_CENTER|DT_SINGLELINE);
            rc.OffsetRect(CSize(-1, -1));
        }
        pDC->SetTextColor(::GetSysColor(COLOR_GRAYTEXT));
    }
    else if (selected)
    {
        pDC->SetTextColor(RGB(255,255,255));
    }
    else
    {
        pDC->SetTextColor(::GetSysColor(COLOR_MENUTEXT));
    }
    pDC->DrawText(itemText, -1, &rc, DT_VCENTER|DT_CENTER|DT_SINGLELINE);
    pDC->SelectObject(oldFont);
}

void CPopupMenu::PaintVeriticalTitle(CDC* pDC, const RECT& rect, COLORREF clrFrom, COLORREF clrTo)
{
    ASSERT(pDC);
    int nStep = 4;//绘制区域的变化步长
    int cxCap = rect.right-rect.left;
    int cyCap = rect.bottom - rect.top;
    int r = GetRValue(clrFrom);
    int g = GetGValue(clrFrom);
    int b = GetBValue(clrFrom);
    if (!(cyCap / nStep))
    {
        return;
    }
    int cr = r / (cyCap/nStep);
    int cg = g / (cyCap/nStep);
    int cb = b / (cyCap/nStep);

    for (int y = 0; y <= cyCap + nStep; y += nStep)
    {
        if (r >= cr)
        {
            r -= cr;
        }
        if (g >= cg)
        {
            g -= cg;
        }
        if (b >= cb)
        {
            b -= cb;
        }
        CBrush brush(RGB(r,g,b));
        pDC->FillRect(&CRect(rect.left, rect.bottom-y, cxCap, rect.bottom-y + nStep), &brush);
    }
}


void CPopupMenu::CreateDrawFont()
{
    LOGFONT lf;
    memset(&lf, 0, sizeof(lf));
    lf.lfOrientation = lf.lfEscapement = 900;
    _tcscpy_s(lf.lfFaceName, _T("宋体"));
    lf.lfHeight = 14;
    lf.lfWeight = FW_THIN;
    lf.lfItalic = FALSE;
    m_titleFont.CreateFontIndirect(&lf);

    memset(&lf, 0, sizeof(lf));
    lf.lfHeight = 14;
    lf.lfWeight = FW_THIN;
    lf.lfItalic = FALSE;
    m_textFont.CreateFontIndirect(&lf);
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值