Why a New Tree Control
First of all, there are lots of custom tree controls available so what's the need for this? In one of my projects, I happened to use several tree controls to show data objects at different levels and I had to deal with user actions. Each time, my tree control has to respond in a different way depending on the selected item. Here, I present what I have (I re-wrote some of my code to use this custom control and I believe that it is more readable and easy to understand now).
How It Works
CSimpleTreeCtrl
"simply" overrides the MFC CTreeCtrl
class and provides some access functions to deal with it. CSimpleTreeCtrl::TreeCtrlItem
is used to add new items in the tree control. You should write your own class (to use it in a better way) and override virtual
functions to be notified by windows messages such as item selection, right click, etc.
CSimpleTreeCtrl
provides the following virtual
functions:
virtual void selChanged ( TreeCtrlItem *item ) {} ;
virtual void lClick ( TreeCtrlItem *item ) {} ;
virtual void lDblClick ( TreeCtrlItem *item ) {} ;
virtual void rClick ( TreeCtrlItem *item ) {} ;
virtual void postCreate ( void ) {} ;
As you noticed, base class has nothing to do with these functions. It simply handles windows messages and calls the virtual
function (I just got bored having to register my message handling functions). The base class also will let CTreeCtrl
do its own stuff, so whenever you receive a lClick()
, you will also get a selChanged()
if this click causes the current selection to change. The only difference is with rClick()
: since in most cases I want right click to change the selected item, I handled this case in my message handler, so it will also send a selChanged()
as well (if a selection exists). You may change this behaviour if you want.
For me, the most useful part is CSimpleTreeCtrl::TreeCtrlItem
. This class provides the following virtual
functions:
virtual void onSelected ( void ) {} ;
virtual void onUnSelected ( void ) {} ;
virtual void onRClick ( CPoint pos ) {} ;
virtual void onLDblClick ( void ) {} ;
virtual void postInsert ( void ) {} ;
It also provides two additional functions which you may find necessary. Thanks to Michael Dunn and his article "Neat Stuff to do in List Controls Using Custom Draw".
void setTextColor ( COLORREF color ) ;
void setBkColor ( COLORREF color ) ;
The default color for item text is black ( RGB(0, 0, 0) ) and item background is white ( RGB(255, 255, 255) ).
You can write your own class handling only required virtual
functions as shown below:
class BaseCtrlItem : public CSimpleTreeCtrl::TreeCtrlItem
{
public:
BaseCtrlItem ( CString name, CMyDataClass *myData )
: CSimpleTreeCtrl::TreeCtrlItem ( name )
{
m_myData = myData ;
} ;
virtual ~BaseCtrlItem () {} ;
virtual void postInsert ( void )
{
} ;
virtual void onRClick ( CPoint pos )
{
} ;
protected:
CMyDataClass *m_myData ;
};
If an item is removed from the tree (using CSimpleTreeCtrl
or CTreeCtrl
functions) related the CSimpleTreeCtrl::TreeCtrlItem
pointer will be removed as well, so you do not need to worry about deleting the item pointers.
There is some more to add to this class but I prefer to keep it as simple as possible. Also, it handles most of the requirements in my project. I would, however, like to hear if there are any useful features to add while keeping it simple.
The demo application creates a new tree control and adds some items in different colors. It also handles the onRClick()
function in items. You can just add SimpleTreeCtrl.h and SimpleTreeCtrl.cpp to your project and enjoy it. The header file should be clear enough for documentation, if it is not, just let me know :-)
Known Problems
CSimpleTreeCtrl
does not hide the base implementation of CTreeCtrl
so users may use the base class functionality as well. However, this may cause some problems. Whenever a CSimpleTreeCtrl::TreeCtrlItem
item is added to the tree, its pointer is added as item data in CTreeCtrl
. If you use HTREEITEM
to add new items and set item data by yourself, CSimpleTreeCtrl
will assume that user data is a CSimpleTreeCtrl::TreeCtrlItem
or derived pointer. If there is no user data, there should not be any problem. CSimpleTreeCtrl::postCreate()
will be called when tree control receives an OnCreate()
message. I noticed that in some cases (according to how you use the tree), that control does not get this message. But I did not check it in detail. If you've got any problem, send me the details.
License
This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below.
A list of licenses authors might use can be found here.