1. 绘制菜单
1> 先用Cmenu::ModifyMenu编程实现传统菜单到自制菜单项的转化
2> 添加响应WM_MEASUREITEM消息 // 在主框架中响应
WM_MEASUREITEM的工作时填充itemWidth和itemHeight
在这个消息中, 设置单个菜单项的宽度
/*
* MEASUREITEMSTRUCT for ownerdraw
*/
typedef struct tagMEASUREITEMSTRUCT {
UINT CtlType; // 菜单项取值 ODT_MENU
UINT CtlID; // 指定了自绘控件的ID值,而对于菜单项则不需要使用该成员
UINT itemID; // 表示菜单项ID
UINT itemWidth; // 指定宽,单位象素,一个菜单项目.在从消息返回之前,自绘菜单项的所有者必需填充这个成员。
UINT itemHeight; // 指定高,单位象素,一个菜单.在从消息返回之前,自绘菜单项的所有者必需填充这个成员。
DWORD itemData; //
} MEASUREITEMSTRUCT, NEAR *PMEASUREITEMSTRUCT, FAR *LPMEASUREITEMSTRUCT;
lpmis->itemWidth = ::GetSystemMetrics (SM_CYMENU) * 4; // 菜单宽度
lpmis->itemHeight = ::GetSystemMetrics (SM_CYMENU); // 菜单高度
SM_CYMENU是系统给顶层菜单画的菜单栏的高度.
3> 添加响应WM_DRAWITEM消息 // 在主框架中响应
typedef struct tagDRAWITEMSTRUCT {
UINT CtlType; // 菜单项取值 ODT_MENU
UINT CtlID; // 指定了自绘控件的ID值,而对于菜单项则不需要使用该成员
UINT itemID; // 表示菜单项ID
UINT itemAction; // 指定绘制行为
UINT itemState; // 指定了当前绘制操作完成后,所绘项的可见状态
HWND hwndItem; // 菜单句柄
HDC hDC; // 指定了绘制操作所使用的设备环境
RECT rcItem; // 指定了将被绘制的矩形区域。这个矩形区域就是上面hDC的作用范围。
ULONG_PTR itemData;
} DRAWITEMSTRUCT;
例子:
// 顶层的弹出菜单
void CMainFrame::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu)
{
if (0 == nIndex)
{
pPopupMenu->ModifyMenu(0, MF_OWNERDRAW | MF_BYPOSITION | MF_GRAYED);
}
CFrameWnd::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu);
}
// 顶层菜单
void CMainFrame::OnInitMenu(CMenu* pMenu)
{
CFrameWnd::OnInitMenu(pMenu);
}
void CMainFrame::OnMeasureItem (int nIDCtl, LPMEASUREITEMSTRUCT lpmis)
{
lpmis->itemWidth = ::GetSystemMetrics (SM_CYMENU) * 4; // 菜单宽度
lpmis->itemHeight = ::GetSystemMetrics (SM_CYMENU) - 3; // 菜单高度
}
void CMainFrame::OnDrawItem (int nIDCtl, LPDRAWITEMSTRUCT lpdis)
{
CDC dc;
dc.Attach(lpdis->hDC);
CString strText = _T(" 新建");
COLORREF clColor = 0;
if (lpdis->itemState & ODS_GRAYED) // 灰化
{
clColor = ::GetSysColor(COLOR_GRAYTEXT);
}
else if (lpdis->itemState & ODS_SELECTED) // 选中
{
clColor = RGB(255, 255, 255);
}
else if (lpdis->itemState & ODS_DISABLED)
{
// clColor = ::GetSysColor(COLOR_D)
}
else
{
clColor = RGB(0, 0, 0);
}
CBrush *pBrush = new CBrush ( ::GetSysColor ( (lpdis->itemState & ODS_SELECTED) ?
COLOR_HIGHLIGHT : COLOR_MENU)
); // 高亮颜色 菜单颜色
// 为选中的菜单项绘制外边框
// dc.FrameRect (&(lpdis->rcItem), pBrush);
dc.FillRect(&(lpdis->rcItem), pBrush);
delete pBrush;
dc.SetTextColor(clColor);
dc.SetBkMode(TRANSPARENT);
dc.TextOut(lpdis->rcItem.left, lpdis->rcItem.top, strText);
dc.Detach();
}
2. 层叠菜单
3. 上下文菜单(右键弹出式菜单)
ON_WM_CONTEXTMENU()
void CChildView::OnContextMenu(CWnd* pWnd, CPoint point)
{
CMenu menu;
menu.LoadMenu (IDR_CONTEXTMENU);
CMenu* pContextMenu = menu.GetSubMenu (0);
for (int i=0; i<5; i++)
pContextMenu->ModifyMenu (ID_COLOR_RED + i,
MF_BYCOMMAND | MF_OWNERDRAW, ID_COLOR_RED + i);
pContextMenu->TrackPopupMenu (TPM_LEFTALIGN |
TPM_LEFTBUTTON |
TPM_RIGHTBUTTON,
point.x,
point.y,
AfxGetMainWnd ());
CWnd::OnContextMenu (pWnd, point);
}