菜单
对话框的系统菜单
//预处理
#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);
}