65.9K
CodeProject 正在变化。 阅读更多。
Home

强大的拥有绘制菜单

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.92/5 (31投票s)

2001年10月24日

2分钟阅读

viewsIcon

746312

downloadIcon

9061

具有背景图片和图标阴影支持的 XP 风格拥有绘制菜单

Sample Image - MenuXP.jpg Sample Image - MenuXP2.jpg Sample Image - MenuXP3.jpg

一个功能齐全的自定义绘制菜单类

CMenuXP 是一个从 CMenu 派生的类,使用了自定义绘制技术。我将其命名为 MenuXP,因为我希望它看起来像 Office XP 和 Windows XP 中找到的菜单,但我未能实现这一点。我遇到的主要困难是将菜单的 3D 边框转换为平面边框,但我希望它仍然对您有用。

我从 Scribble 示例应用程序构建了这个类,并且部分绘制代码是从 CCoolMenuManager 类复制而来。此外,我还使用了 BCGControlBar 中的一个名为 CBCGKeyHelper 的类来显示加速键文本。

特点

  1. 带有图标的菜单,如 Office 97 中所示
  2. 弹出菜单的任何级别上的侧边栏
  3. 支持按钮式菜单项,例如在 Microsoft Office 套件的一些绘图工具栏中找到的
  4. 所有颜色、字体和大小都可以自定义

引言

菜单中的一个项目由 CMenuXPItem 类表示。一些进一步的类从它派生,提供方便的使用

  • CMenuXPText 表示带有文本和可选图标的普通菜单项
  • CMenuXPSeparator 表示分隔符
  • CMenuXPSideBar 表示弹出菜单左侧的侧边栏
  • CMenuXPButton 表示仅包含图标的按钮菜单项

了解这些将有助于您理解代码。

如何用作弹出菜单

  1. 构造一个 CMenuXP 实例
  2. 调用 CreatePopupMenu
  3. 如果需要,使用 AddSideBar 添加一个侧边栏
  4. 使用 AppendODMenu 添加一些菜单项
  5. 如果有第二级弹出菜单,使用步骤 1 到 4 构建它,并使用 AppendODPopup 将其添加到当前菜单
  6. 像往常一样调用 TrackPopupMenu

示例代码如下所示

void CMenuXPAppView::OnContextMenu(CWnd* pWnd, CPoint point)
{
	CMenuXP	*pMenu = new CMenuXP;
	pMenu->CreatePopupMenu();

	pMenu->AddSideBar(new CMenuXPSideBar(24, "MenuXP"));
	pMenu->AppendODMenu(0, new CMenuXPText(10, "First Item",
                               AfxGetApp()->LoadIcon(IDI_ICON1)));
	pMenu->AppendODMenu(0, new CMenuXPText(11, "Second Item",
                               AfxGetApp()->LoadIcon(IDI_ICON2)));
	pMenu->AppendODMenu(0, new CMenuXPText(12, "Another Item",
                               AfxGetApp()->LoadIcon(IDI_ICON3)));
	pMenu->AppendODMenu(0, new CMenuXPText(13, "No Icon"));

	CMenuXP *pPopup = new CMenuXP;
	pPopup->CreatePopupMenu();
	pPopup->AppendODMenu(0, new CMenuXPButton(21,
                                AfxGetApp()->LoadIcon(IDI_ICON4)));
	pPopup->AppendODMenu(0, new CMenuXPButton(22,
                                AfxGetApp()->LoadIcon(IDI_ICON5)));
	pPopup->AppendODMenu(0, new CMenuXPButton(23,
                                AfxGetApp()->LoadIcon(IDI_ICON6)));
	pPopup->Break();
	pPopup->AppendODMenu(0, new CMenuXPButton(24,
                                AfxGetApp()->LoadIcon(IDI_ICON7)));
	pPopup->AppendODMenu(0, new CMenuXPButton(25,
                                AfxGetApp()->LoadIcon(IDI_ICON8)));
	pPopup->AppendODMenu(0, new CMenuXPButton(26,
                                AfxGetApp()->LoadIcon(IDI_ICON9)));
	pPopup->Break();
	pPopup->AppendODMenu(0, new CMenuXPButton(27,
                                AfxGetApp()->LoadIcon(IDI_ICON10)));
	pPopup->AppendODMenu(0, new CMenuXPButton(28,
                                AfxGetApp()->LoadIcon(IDI_ICON11)));
	pPopup->AppendODMenu(0, new CMenuXPButton(29,
                                AfxGetApp()->LoadIcon(IDI_ICON12)));

	pMenu->AppendODPopup(0, pPopup, new CMenuXPText(0, "Popup",
                                AfxGetApp()->LoadIcon(IDI_ICON1)));

	pMenu->TrackPopupMenu(TPM_LEFTBUTTON, point.x, point.y, this);

	delete pMenu;
}

在堆上构造的对象将自动销毁,除了需要手动销毁的顶级弹出菜单。

请记住在您的父窗口的 WM_MEASUREITEM 处理程序中添加以下代码

void CMenuXPAppView::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
	// TODO: Add your message handler code here and/or call default
	HMENU hMenu = AfxGetThreadState()->m_hTrackingMenu;
	CMenu	*pMenu = CMenu::FromHandle(hMenu);
	pMenu->MeasureItem(lpMeasureItemStruct);

	CView::OnMeasureItem(nIDCtl, lpMeasureItemStruct);
}

就这样了,希望这对您有用。欢迎提交错误报告和改进建议。

许可证

本文没有明确的许可证附加到它,但可能包含在文章文本或下载文件本身中的使用条款。如有疑问,请通过下面的讨论区联系作者。

作者可能使用的许可证列表可以在此处找到。

© . All rights reserved.