自定義菜單

菜單

對話框的系統菜單
//預處理
#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);
}

在這裏插入圖片描述

發佈了74 篇原創文章 · 獲贊 15 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章