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

WTL - 按钮菜单

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.50/5 (2投票s)

2000年7月28日

viewsIcon

113989

downloadIcon

2190

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

Sample Image - ButtonMenu.gif

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");
当用户选择菜单项时,将向对话框发送一条消息。

不足之处

  • 尚未提供一个可以正确初始化控件的 Create 方法
  • 未响应 BS_DEFPUSHBUTTON 标志

    历史

    2000 年 8 月 14 日 - 修复了 OnDraw 方法,使其在调用 GetWindowText() 时使用 DRAWITEMSTRUCT 的 HWND 而不是按钮的 HWND。这修复了一个错误,导致同一对话框上的两个不同的 CButtonMenu 始终绘制相同的标题。
  • © . All rights reserved.