<!-- Article Starts -->
ComboTree is a hybrid
ComboBox with a tree control replacing the drop down
ListBox. Implementing a hierarchy of choices using multiple dependant combo or list boxes can take up a lot of screen space and can be awkward to use. A dropdown tree control can be a good replacement. As an option, the
ComboTree supports a tree with three-state checkboxes for convenient multiple selection from a hierarchy of choices.
It has been tested and works on Win2000, Win98 and NT 4.0. Due to differences between these systems the technique of positioning a substitute control in place of the
ListBox of an existing
ComboBox upon receiving a
CBN_DROPDOWN message couldn't be relied on. Instead of subclassing and modifying the behavior, this control totally replaces the existing
The previous version of
ComboTree used a tree control with the
WS_POPUP style that was a child of the
ComboTree's parent window. The
WS_POPUP style however caused the parent dialog to become inactive when the tree was dropped down. This version of
ComboTree creates the tree control as a child of the Desktop window like the
ComboBox does with its
ComboTree subclasses the
ComboTree's parent window to intercept messages when the tree is dropped down and it also forwards keyboard messages to the tree. The built in tree control's tooltips did not work in this configuration, so the
ComboTree includes a custom tooltip control to provide them.
Here are the steps needed to use a
ComboTree in your project:
- Just as you normally would, place a
ComboBox on the dialog. Set the dropdown height. The hybrid control will use the same sizes and positions as the original.
- Add all files named
ComboTree*.cpp & .h and Subclass.cpp, Subclass.h, PupText.cpp, PupText.h to your project.
- If you will be using the checked tree style, import the bitmap file
ComboTreeCheckboxes.bmp and give it a resource Id of
"COMBOTREECHECKS" (Note: The quotes are important! The quoted resource form is used to allow the bitmap to be optional.) Alternatively, you may open the resource file for the sample project,
ComboTreeShow.rc and drag and drop the "COMBOTREECHECKS" bitmap into your project's resource tab.
- In the header file for the dialog, add an include for
ComboTree.h at the top. Manually add a
ComboTree member variable, referred to as
- Create the
ComboTree in the dialog's
OnInitDialog() function. If you are using checkboxes you must call
SetHasCheckboxes(TRUE) before creating the control. Create the
ComboTree by subclassing the
ComboBox from step one. Example syntax for creating a checked tree:
(To create a tree without checkboxes, omit the
- Populate the control using the
- Just as you normally would, use Class Wizard or edit manually to add handlers for the
ComboBox notifications you want.
ComboTree uses the same
CBN_* notifications as a normal
Important note: Don't use ClassWizard and the DDX/DDV mechanism to add and associate member variables with the
ComboBox. Once the original
ComboBox control is subclassed it won't exist anymore.
notifications are supported, but the following ones are:
When accessing the control, call the
functions directly instead of sending messges. The following access functions which emulate their
equivalents are supported.
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);
The access functions differ in a couple of important ways from normal
CComboBox functions. Functions that accept a string use the full path of the tree heirachy. For example to select the "Chipmunk" node use the full path to it:
hNode = m_ComboTree.SelectString ("Animals/Mammals/Chipmunk");
To populate the
CComboBox use the
AddString () function. The function will add nodes for all levels of the path that don't already exist. The
HTREEITEM returned is for the end node. Example:
HTREEITEM hNode = m_ComboTree.AddString ("Plants/Trees/Oak");
ComboTree functions accept or return a
HTREEITEM where the
CComboBox equivalent uses a
CB_ERR is still used as an error return value in functions where the
CComboBox equivalent uses
0 as a success return value.
In addition to the
CComboBox emulation functions are the following extensions:.
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 GetNextCheckedItem( HTREEITEM hItem );
HTREEITEM GetPrevCheckedItem( HTREEITEM hItem );
GetTreePath () and GetCurrentTreePath() return the text of the tree item prefixed with the concatenated text of its parent nodes.
Functions that contain "Check" in the name only are valid if the tree has a checked style
Three functions allow direct access to
ComboTree child controls.
ComboTreeDropList& GetTree () ;
ComboTreeEdit& GetEdit () ;
ComboTreeButton& GetDropDownButton ();
GetTree(), GetEdit () and GetDropDownButton() allow direct access to the tree, edit and button controls. (Note: Use this direct access only in ways that do not conflict with the
CBN_* notifications and maintenance of control state.)
ComboTree doesn't have support for keyboard input to select tree items from within the edit control at this time. Text lookup similar to that of a drop down style combo box could be added with some additional search functionality. The edit control is currently read only.
- 8 Aug 2000 - Fixed painting bug reported by Steve Roach as well as a few other things I overlooked in emulating the droplist style ComboBox, like highlighting the control when it it gets focus, dropping down the tree when the edit gets a mouse click and disabling mouse and context menu text manipulation.
- 9 May 2003 - New version of
ComboTree fixes all the known bugs, adds three-state checkbox. Thanks to all who reported them! Credits to Magerusan Grigore Cosmin's article for fix to dialog inactivation when tree is dropped down, Paul DiLascia's article for custom tooltips and Zafir Anjum article for three-state checkboxes.