WTL - 按钮菜单






3.50/5 (2投票s)
2000年7月28日

113989

2190
使用 WTL 创建实现下拉菜单的简单按钮。

DevStudio 的“工具|自定义”菜单显示一个包含带有箭头按钮的对话框。按下按钮时,将显示一个下拉菜单。我需要在我的 ATL 应用程序中使用此功能,但不想使用 MFC 的开销,也不想处理 Win32 的复杂性。因此,我借鉴了 Norm Almond 出色的 Cool Push Menu Button 示例,并将其移植到 WTL,同时简化了其功能。我并不是暗示 Norm 开发的有什么问题……只是该控件的功能比我需要的要多。如果时间允许,我最终会将他的整个控件移植到 WTL。
注意事项
CButtonMenu 继承自 CButtonMenuImpl。为了在按钮上绘制箭头,CButtonMenuImpl 需要设置 BS_OWNERDRAW 样式。但是,这将向 CButtonMenuImpl 的父窗口发送 WM_DRAWITEM 消息,而不是发送给 CButtonMenuImpl 本身。通过子类化父窗口的 HWND,CButtonMenuImpl 可以劫持该消息并单独处理它。为此,CButtonMenuImpl 具有一个私有成员变量 CContainedWindow,用于子类化父窗口。然后,使用 ALT_MSG_MAP() 宏,我们可以捕获该消息
class CButtonMenuImpl : ...
{
CContainedWindow m_Parent;
public:
    CButtonMenuImpl():
      m_Parent(this,1){}
    {other code}
protected:
    typedef CWindowImpl<T, TBase, TWinTraits> baseClass;
    BEGIN_MSG_MAP(CButtonMenuImpl)
        other msgs
    ALT_MSG_MAP(1)
        MESSAGE_HANDLER(WM_DRAWITEM, OnDrawItem)
    END_MSG_MAP()
        {other code}
};
最后,为了简单地使用此控件,CButtonMenu 提供了一个运算符重载class CButtonMenu : public CButtonMenuImpl<CButtonMenu>
{
public:
    DECLARE_WND_SUPERCLASS(_T("WTL_CButtonMenu"), GetWndClassName())
//ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
    CButtonMenu& operator=(HWND hWnd)
    {
        if ( m_hWnd )
            DestroyWindow();
        if ( ::IsWindow(hWnd) )
            SubclassWindow(hWnd);
        return *this;
    }
};
以下是如何使用对话框中已有的按钮初始化 CButtonMenu 的示例    // Member variable of dialog
    CButtonMenu btnMenu;        
    // Somewhere in WM_INITDIALOG handler
    btnMenu = GetDlgItem(IDC_BTN_ABOUT);
    btnMenu.AddMenuItem(IDC_MNU_ONE,"Windows");
    btnMenu.AddMenuItem(IDC_MNU_TWO,"Template");
    btnMenu.AddMenuItem(IDC_MNU_THREE,"",MF_SEPARATOR);
    btnMenu.AddMenuItem(IDC_MNU_FOUR,"Library");
当用户选择菜单项时,将向对话框发送一条消息。
不足之处
