A Fully Featured Owner-draw Menu Class
CMenuXP
is a class derived from CMenu
using ownerdraw technology. I named it MenuXP
because I expected it to be like the menus found in Office XP and Windows XP, but I failed to accomplish it. The main difficulty that I had was converting the 3D border of the menu into a flat one, but I hope it is still useful to you.
I constructed the class from the Scribble sample application and some of the drawing code is copied from the CCoolMenuManager
class. Additionally, I have also used a class named CBCGKeyHelper
from BCGControlBar
to show the accelerator key text.
Features
- Menu with icons, like in Office 97
- A sidebar in any level of the popup menu
- Supports button-style menu items, such as is found in some drawing toolbars of the Microsoft Office suite
- All colors, fonts and sizes can be customized
Introduction
An item in the menu is represented by the CMenuXPItem
class. Some further classes are derived from it which provide convenient uses:
CMenuXPText
presents a normal menu item with text and an optional icon CMenuXPSeparator
presents a separator CMenuXPSideBar
presents a sidebar on the left of a popup menu CMenuXPButton
presents a button only menu item, which contains the icon only
Knowing this will help you to understand the code.
How to Use as a Popup Menu
- Construct a
CMenuXP
instance - Call
CreatePopupMenu
- Add a sidebar using
AddSideBar
if needed - Add some menu items using
AppendODMenu
- If there is second level popup menu, construct it using steps 1 to 4 and add it to the current menu using
AppendODPopup
- Call
TrackPopupMenu
as normal
The example code would be like this:
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;
}
The object constructed on the heap will be destroyed automatically, except for the toplevel popup menu which will need to be destroyed manually.
Remember to add the code below in the WM_MEASUREITEM
handler of your parent window:
void CMenuXPAppView::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
HMENU hMenu = AfxGetThreadState()->m_hTrackingMenu;
CMenu *pMenu = CMenu::FromHandle(hMenu);
pMenu->MeasureItem(lpMeasureItemStruct);
CView::OnMeasureItem(nIDCtl, lpMeasureItemStruct);
}
That's all, I hope this is useful to you. Bug reports and improvements are welcome.
License
This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below.
A list of licenses authors might use can be found here.