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

ComboTree

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.57/5 (15投票s)

2000年7月28日

viewsIcon

246874

downloadIcon

6937

带树控件下拉菜单的组合框

Sample Image

ComboTree 是一个混合的 ComboBox,它用一个树形控件代替了下拉列表框 ListBox。使用多个依赖的组合框或列表框来实现选择的层级结构会占用大量屏幕空间,并且使用起来也很麻烦。下拉式树形控件可以很好地替代它们。作为一种选择,ComboTree 支持带有三态复选框的树,可以方便地从选择层级结构中进行多选。

它已经在 Win2000, Win98 和 NT 4.0 上进行了测试并能正常工作。由于这些系统之间的差异,在收到 CBN_DROPDOWN 消息时,将一个替代控件定位在现有 ComboBoxListBox 位置的技术并不可靠。该控件没有通过子类化和修改行为,而是完全替换了现有的 ComboBox

ComboTree 的前一个版本使用的是一个带有 WS_POPUP 样式的树形控件,它是 ComboTree 父窗口的子窗口。然而,WS_POPUP 样式会导致父对话框在树形控件下拉时变得不活跃。这个版本的 ComboTree 创建的树形控件是桌面窗口的子窗口,就像 ComboBox 用它的 ListBox 做的那样。ComboTreeComboTree 的父窗口进行子类化,以便在树形控件下拉时拦截消息,并且它还将键盘消息转发给树形控件。内置树形控件的工具提示在此配置下不起作用,因此 ComboTree 包含一个自定义工具提示控件来提供它们。

以下是将 ComboTree 用于您的项目所需的步骤:

  1. 就像平常一样,将一个 ComboBox 放置在对话框上。设置下拉高度。混合控件将使用与原始控件相同的尺寸和位置。
  2. 将所有名为 ComboTree*.cpp & .h 和 Subclass.cpp, Subclass.h, PupText.cpp, PupText.h 的文件添加到您的项目中。
  3. 如果您将使用带复选框的树样式,请导入位图文件 ComboTreeCheckboxes.bmp,并给它一个资源 ID "COMBOTREECHECKS"(注意:引号很重要!引用的资源形式用于允许位图是可选的。) 或者,您也可以打开示例项目 ComboTreeShow.rc 的资源文件,然后将 "COMBOTREECHECKS" 位图拖放到您的项目的资源选项卡中。
  4. 在对话框的头文件中,在顶部添加一个 ComboTree.h 的包含。手动添加一个 ComboTree 成员变量,下面称之为 m_ComboTree
  5. 在对话框的 OnInitDialog() 函数中创建 ComboTree。如果您使用复选框,则必须在创建控件之前调用 SetHasCheckboxes(TRUE)。通过对第一步中的 ComboBox 进行子类化来创建 ComboTree。创建带复选框树的示例语法:
    m_ComboTree.SetHasCheckboxes(TRUE);
    m_ComboTree.SubclassDlgItem (IDC_COMBO_TREE);

    (要创建一个不带复选框的树,请省略 SetHasCheckboxes() 调用。)
  6. 使用 AddString() 函数填充控件。
  7. 就像平常一样,使用类向导或手动编辑来为您想要的 ComboBox 通知添加处理程序。ComboTree 使用与普通 ComboBox 相同的 CBN_* 通知。

使用注意事项

重要提示:不要使用类向导和 DDX/DDV 机制来添加成员变量并将它们与 ComboBox 关联。一旦原始 ComboBox 控件被子类化,它就不再存在了。

并非所有 ComboBox 通知都支持,但以下通知是支持的:
ON_CBN_SELENDOK(IDC_COMBO_TREE, OnSelendokComboTree)
ON_CBN_SELENDCANCEL(IDC_COMBO_TREE, OnSelendcancelComboTree)
ON_CBN_KILLFOCUS(IDC_COMBO_TREE, OnKillfocusComboTree)
ON_CBN_SELCHANGE(IDC_COMBO_TREE, OnSelchangeComboTree)
ON_CBN_DBLCLK(IDC_COMBO_TREE, OnDblclkComboTree)
ON_CBN_SETFOCUS(IDC_COMBO_TREE, OnSetfocusComboTree)
ON_CBN_CLOSEUP(IDC_COMBO_TREE, OnCloseupComboTree)
ON_CBN_DROPDOWN(IDC_COMBO_TREE, OnDropdownComboTree)
访问控件时,请直接调用 ComboTree 函数,而不是发送消息。以下访问函数模拟了它们的 CComboBox 等效函数,并且是支持的。
void SetWindowText (LPCTSTR Text);
CString GetWindowText ();
int GetLBText (HTREEITEM hItem, CString& rText);

HTREEITEM AddString ( LPCTSTR lpszString);
HTREEITEM FindString ( LPCTSTR lpszString, HTREEITEM hParent = NULL);
HTREEITEM SelectString( LPCTSTR lpszString, HTREEITEM hParent = NULL);

HTREEITEM GetCurSel ();
int   SetItemData (HTREEITEM hItem, DWORD dwItemData);
DWORD GetItemData (HTREEITEM hItem);
void ShowDropDown( BOOL bShowIt = TRUE );
void ResetContent ();
int  SetDroppedWidth( UINT nWidth );
int  GetDroppedWidth( );
BOOL GetDroppedState( );
int  DeleteString( HTREEITEM hItem );
void GetDroppedControlRect (LPRECT pRect);

访问函数与普通的 CComboBox 函数在几个重要方面有所不同。接受字符串的函数使用树形层级的完整路径。例如,要选择 "Chipmunk" 节点,请使用其完整路径:

hNode = m_ComboTree.SelectString ("Animals/Mammals/Chipmunk");

使用 AddString () 函数来填充 CComboBox。该函数将为路径中所有不存在的层级添加节点。返回的 HTREEITEM 是指向结束节点的。

HTREEITEM hNode  = m_ComboTree.AddString ("Plants/Trees/Oak");

ComboTree 函数接受或返回一个 HTREEITEM,而 CComboBox 等效函数使用 ListBox 索引。在等效函数使用 0 作为成功返回值的情况下,CB_ERR 仍然被用作错误返回值。

除了 CComboBox 模拟函数之外,还有以下扩展:

// NOTIFY_TREECOMBO_CHECK notification message for check event. 
// Message map handler example: 
ON_CONTROL (NOTIFY_TREECOMBO_CHECK, IDC_COMBO_TREE, OnComboTreeCheck)

CString GetTreePath (HTREEITEM hItem);
CString GetCurrentTreePath ();
TCHAR GetPathDelimiter ();
void SetPathDelimiter (TCHAR Delimiter);
int  SetDroppedHeight (UINT nHeight);
int  GetDroppedHeight ();
HTREEITEM FindChildItemData(DWORD SearchData, HTREEITEM hItem = NULL) ;
HTREEITEM FindChildItem (LPCTSTR Label, HTREEITEM hItem = NULL) ;
HTREEITEM GetLastItem( HTREEITEM hItem ) ;
HTREEITEM GetNextItem( HTREEITEM hItem ) ;
HTREEITEM GetPrevItem( HTREEITEM hItem ) ;
HTREEITEM GetLastSibling( HTREEITEM hItem ) ;
void CollapseBranch( HTREEITEM hItem) ;
void ExpandBranch( HTREEITEM hItem ) ;
void CollapseAllSiblings( HTREEITEM hNode );
BOOL SetHasCheckboxes (BOOL bHasCheckboxes);
BOOL GetHasCheckboxes ();
BOOL SetCheck( HTREEITEM hItem, BOOL bChecked = TRUE );
BOOL IsItemChecked(HTREEITEM hItem);
HTREEITEM GetFirstCheckedItem();
HTREEITEM GetNextCheckedItem( HTREEITEM hItem );
HTREEITEM GetPrevCheckedItem( HTREEITEM hItem );

GetTreePath () 和 GetCurrentTreePath() 返回树形项的文本,前面加上其父节点连接的文本。

名称中包含 "Check" 的函数仅在树形控件具有选中样式时才有效。

三个函数允许直接访问 ComboTree 的子控件。

ComboTreeDropList& GetTree () ;
ComboTreeEdit& GetEdit () ;
ComboTreeButton& GetDropDownButton ();

GetTree(), GetEdit () 和 GetDropDownButton() 允许直接访问树、编辑框和按钮控件。(注意:只能以不与 CBN_* 通知和控件状态维护冲突的方式使用此直接访问。)

ComboTree 目前不支持从编辑框内部选择树项的键盘输入。可以通过添加一些额外的搜索功能来实现类似于下拉式组合框的文本查找。编辑框目前是只读的。

历史

  • 2000 年 8 月 8 日 - 修复了 Steve Roach 报告的绘画错误以及我在模拟下拉列表式 ComboBox 时忽略的一些其他问题,例如当控件获得焦点时突出显示该控件,当编辑框鼠标单击时下拉树,以及禁用鼠标和上下文菜单的文本操作。
  • 2003 年 5 月 9 日 - ComboTree 的新版本修复了所有已知错误,并添加了三态复选框。感谢所有报告错误的人!感谢 Magerusan Grigore Cosmin 的文章解决了树形控件下拉时对话框不活跃的问题,感谢 Paul DiLascia 的文章提供了自定义工具提示,感谢 Zafir Anjum 的文章提供了三态复选框。
© . All rights reserved.