📄 titledmenu.shtml
字号:
<html>
<!-- Header information-->
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<meta NAME="Author" CONTENT="Mark E. Pennell">
<title>Section - Title</title>
</head>
<!-- Set background properties -->
<body background="../fancyhome/back.gif" bgcolor="#FFFFFF" link="#B50029" vlink="#8E2323"
alink="#FF0000">
<h3 align="center"><font COLOR="#AOAO99">Creating Popup Menus with Titles</font></h3>
<hr align="center">
<!-- Author and contact details -->
<p>This article was contributed by <a HREF="#author">Mark E. Pennell</a>. </p>
<h4><br>
<!-- The article... -->Introduction</h4>
<p>Popups, popups everywhere! Have you noticed that we now live in an age of the
endless collection of popup menus? In practically every modern application, there
exists several UI objects which have their own popup menus. One must admit that
these "context" menus have provided a needed boost in working with applications
with 'heavy' UIs. However, there are times where the user of your application may be
a little confused about to which 'item' the invoked popup menu refers. </p>
<table border="0" width="100%" height="101">
<tr>
<td width="62%" height="97">Let's give an example, however contrived it may be. Imagine
using a home architecting product in which you can click items in your room layout to
invoke context menus. When you click on the chair in the living room, you get the context
menu to the right. Now, you select the 'Remove' command. <font color="#FF0000">Oops!</font>
Your carefully designed Persian rug disappears from under the chair you thought you had
selected.</td>
<td width="38%" height="97"> <img src="menu1.gif" width="109" height="81"
alt="menu1.gif (2879 bytes)"></td>
</tr>
</table>
<p>Okay ... maybe not the best example I could have found, but hopefully you are both
laughing (not just at me) and understanding that there are cases where a slightly more
user friendly approach to context menus might be useful. So what might this be?</p>
<h4>Titled Popup Menus</h4>
<p>There has been a recent UI trend involving the addition of titles to popup menus.
These titles are used to convey the exact object to which the context applies.
These are also being used to prompt the user with clear information on why they
should make a menu selection. As an example of the latter, you may have seen
pulldown toolbar buttons where you can also select the 'default' action to occur when the
toolbar button is left clicked. It is common to see the popup menu for the button
start with the title "Set Default" appearing in bold as the first item in the
menu. This item is not selectable, but is a visual indicator better describing the
use/reason for the menu.</p>
<table border="0" width="100%">
<tr>
<td width="62%">So to finish our example above, to the right is a titled context menu
which might have better helped our user.</td>
<td width="38%"> <img src="menu2.gif" width="126" height="103"
alt="menu2.gif (3813 bytes)"></td>
</tr>
</table>
<p>Disclaimer for UI purists - This article is not meant to give an opinion on whether or
not this is good UI style, but rather to provide information on implementing this feature
to those who are interested. If you wish to add titled popup menus to your product,
I hope this code helps you accomplish your goal.</p>
<h4>Method 1 - SetMenuDefaultItem(...)</h4>
<p>The Win32 API provides a single function which will "bold" a menu item to
indicate that it is the default menu item. You can disable the menu item as
well to meet most of our goals above. The item will still invert as you move
the mouse over it, which is not as desireable as our example/description above.</p>
<pre><font color="#990000">
//
// This function adds a title entry to a popup menu
//
void AddMenuTitle(CMenu* popup, LPCSTR title)
{
// insert a separator item at the top
popup->InsertMenu(0, MF_BYPOSITION | MF_SEPARATOR, 0, title);
// insert title item
// note: item is not selectable (disabled) but not grayed
popup->InsertMenu(0, MF_BYPOSITION | MF_STRING | MF_DISABLED, 0, title);
SetMenuDefaultItem(popup->m_hMenu, 0, TRUE);
}
</font></pre>
<h4>Method 2 - Owner Drawn Item</h4>
<p>This method is more involved, but it gives you full control over the display
of the titled item. With this method, moving the mouse over the item does
not cause it to highlight as in Method 1.<p>
<p>This method also doubles as a good tutorial on owner drawn menu items in general.<p>
<h4>Utilization Example Code</h4>
<p>The following steps can be used to create titled popup menus in your application
utilizing the supplied implementation code for Method 2:
<ol>
<li>Add the supplied helper code and header to your project</li>
<li>Add OnMeasureItem and OnDrawItem to the window handling the popup menu</li>
<li>Call the helper functions to handle the measuring and drawing of your popup menu title
item</li>
<li>Setup the popup menu to have a title just before displaying (tracking) the popup menu</li>
</ol>
<p>The following is a code snippet from a simple dialog class which added the above example
titled popup menu:</p>
<pre><font color="#990000">
<p>void CExampleDlg::OnContextMenu(CWnd* pWnd, CPoint point)
{
// load the popup menu to display
CMenu menu;
menu.LoadMenu(idrMenu1);
CMenu* popup = menu.GetSubMenu(0);
</font><font color="#000080"> // call the helper function to setup this as a titled popup menu
AddMenuTitle(popup);
</font><font color="#990000">
// display the popup menu
popup->TrackPopupMenu(TPM_LEFTALIGN, point.x, point.y, this);
}
void CExampleDlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
if (ODT_MENU == lpDrawItemStruct->CtlType)
{
</font><font color="#000080"> // call our helper function to draw the item title
DrawPopupMenuTitle(lpDrawItemStruct, "Persian Rug");
</font><font color="#990000"> }
else
{
CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct);
}
}
void CExampleDlg::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
if (ODT_MENU == lpMeasureItemStruct->CtlType)
{
</font><font color="#000080">// call our helper function to measure the item title
MeasurePopupMenuTitle(lpMeasureItemStruct, "Persian Rug");</font><font color="#990000">
}
else
{
CDialog::OnMeasureItem(nIDCtl, lpMeasureItemStruct);
}
}
</p>
</font></pre>
<h2>The header file.... (TitledMenu.h)...</h2>
<pre><font color="#990000">
<p>#ifndef __TitledMenu_h
#define __TitledMenu_h
void AddMenuTitle(CMenu* popup);
void MeasurePopupMenuTitle(LPMEASUREITEMSTRUCT mi, LPCSTR menuTitle);
void DrawPopupMenuTitle(LPDRAWITEMSTRUCT di, LPCSTR menuTitle);
#endif
</p></font></pre>
<h2>The Implementation File (TitledMenu.cpp)</h2>
<pre><font color="#990000">
<p>#include "stdafx.h"
#include "TitledMenu.h"
//
// This function adds a title entry to a popup menu
//
void AddMenuTitle(CMenu* popup)
{
// insert a separator item at the top
popup->InsertMenu(0, MF_BYPOSITION | MF_SEPARATOR, 0, (LPSTR)0);
// insert an empty owner-draw item at top to serve as the title
// note: item is not selectable (disabled) but not grayed
popup->InsertMenu(0, MF_BYPOSITION | MF_OWNERDRAW | MF_STRING | MF_DISABLED, 0, (LPSTR)0);
}
//
// This function creates the bold font for the popup menu's title
//
static HFONT CreatePopupMenuTitleFont()
{
// start by getting the stock menu font
HFONT font = (HFONT)GetStockObject(ANSI_VAR_FONT);
if (font)
{
// now, get the complete LOGFONT describing this font
LOGFONT lf;
if (GetObject(font, sizeof(LOGFONT), &lf))
{
// set the weight to bold
lf.lfWeight = FW_BOLD;
// recreate this font with just the weight changed
font = CreateFontIndirect(&lf);
}
}
// return the new font - Note: Caller now owns this GDI object
return font;
}
//
// This is a helper function to measure the popup menu's title item
//
void MeasurePopupMenuTitle(LPMEASUREITEMSTRUCT mi, LPCSTR menuTitle)
{
// create the font we will use for the title
HFONT font = CreatePopupMenuTitleFont();
if (font)
{
// get the screen dc to use for retrieving size information
CDC dc;
dc.Attach(::GetDC(NULL));
// select the title font
CFont* old = (CFont*)dc.SelectObject(CFont::FromHandle(font));
// compute the size of the title
CSize size = dc.GetTextExtent(menuTitle);
// deselect the title font
dc.SelectObject(old);
// delete the title font
DeleteObject(font);
// add in the left margin for the menu item
size.cx += GetSystemMetrics(SM_CXMENUCHECK)+8;
// return the width and height
mi->itemWidth = size.cx;
mi->itemHeight = size.cy;
}
}
//
// This is a helper function to draw the popup menu's title item
//
void DrawPopupMenuTitle(LPDRAWITEMSTRUCT di, LPCSTR menuTitle)
{
// create the font we will use for the title
HFONT font = CreatePopupMenuTitleFont();
if (font)
{
// create the background menu brush
HBRUSH bgb = CreateSolidBrush(GetSysColor(COLOR_MENU));
// fill the rectangle with this brush
FillRect(di->hDC, &di->rcItem, bgb);
// delete the brush
DeleteObject(bgb);
// set text mode to transparent
int mode = SetBkMode(di->hDC, TRANSPARENT);
// set text color to menu text color
COLORREF color = SetTextColor(di->hDC, GetSysColor(COLOR_MENUTEXT));
// select this font into the dc
HFONT old = (HFONT)SelectObject(di->hDC, font);
// add the menu margin offset
di->rcItem.left += GetSystemMetrics(SM_CXMENUCHECK)+8;
// draw the text left aligned and vertically centered
DrawText(di->hDC, menuTitle, -1, &di->rcItem, DT_SINGLELINE|DT_VCENTER|DT_LEFT);
// deselect the font
SelectObject(di->hDC, old);
// restore the text background mode
SetBkMode(di->hDC, mode);
// restore the text color
SetTextColor(di->hDC, color);
}
}
</p>
</font></pre>
<h4><a name="Author"></a>About the Author</h4>
<p><a href="mailto:mark@funtown.com">Mark E. Pennell</a> is a Senior Engineer for
Visioneer, Inc. of Fremont, CA., and a former Windows Programming instructor for the
University of California - Santa Cruz Extension. Mark telecommutes to work from his
home in Austin, TX.</p>
<!-- Remember to update this -->
<p>Last updated: 13 May 1998 </p>
<hr>
<TABLE BORDER=0 WIDTH="100%" >
<TR>
<TD WIDTH="33%"><FONT SIZE=-1><A HREF="http://www.codeguru.com">Goto HomePage</A></FONT></TD>
<TD WIDTH="33%">
<CENTER><FONT SIZE=-2>© 1998 Zafir Anjum</FONT> </CENTER>
</TD>
<TD WIDTH="34%">
<DIV ALIGN=right><FONT SIZE=-1>Contact me: <A HREF="mailto:zafir@home.com">zafir@home.com</A> </FONT></DIV>
</TD>
</TR>
</TABLE>
</BODY>
</HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -