DevStudio's Tools|Customize menu displays a dialog box that contains a button control with an arrow on it. When pressed, the button will display a drop-down menu. I needed this feature in my ATL applications, but didn't want the overhead of MFC or the headache of Win32. So I borrowed from Norm Almond's excellent example of Cool Push Menu Button and ported it to WTL, simplifying it's functionality along the way. I'm not implying anything was wrong with what Norm developed...the control just did more than I needed it to. I will eventually port his entire control to WTL, when time allows.
CButtonMenu is derived from
CButtonMenuImpl. To draw the arrow on the button,
CButtonMenuImpl needs to have the BS_OWNERDRAW style set. However, this will send the WM_DRAWITEM msg to the parent of the
CButtonMenuImpl, and not the
CButtonMenuImpl itself. By subclassing the parent HWND, the
CButtonMenuImpl can hijack the msg and handle it alone. To do this, the
CButtonMenuImpl has a private member
CContainedWindow variable that subclasses the parent. Then, using the ALT_MSG_MAP() macro, we can catch the msg:
class CButtonMenuImpl : ...
typedef CWindowImpl<T, TBase, TWinTraits> baseClass;
Finally, to make simple use of this control,
provides an operator overload:
class CButtonMenu : public CButtonMenuImpl<CButtonMenu>
CButtonMenu& operator=(HWND hWnd)
if ( m_hWnd )
if ( ::IsWindow(hWnd) )
Here's an example of how to initialize a
with a button already on a dialog:
btnMenu = GetDlgItem(IDC_BTN_ABOUT);
When the user selects a menu item, a msg will be sent to the dialog.
Doesn't provide a Create method that will initialize the control properly (yet)
Doesn't respond to the BS_DEFPUSHBUTTON flag
August 14, 2000 - Fixed the OnDraw method to use the DRAWITEMSTRUCT's HWND instead of the Button's HWND when calling GetWindowText(). This fixed a bug that resulted in two different CButtonMenu's on the same dialog always painting the same caption.