Click here to Skip to main content
15,888,733 members
Articles / Desktop Programming / MFC

A Multi-selectable Tree Control Supports Transparent Selection Rectangle

Rate me:
Please Sign up or sign in to vote.
4.68/5 (36 votes)
29 Dec 2010CPOL2 min read 207.7K   67   20
A multi-select tree control that is based on Richard's implementation

Introduction

Sometimes, we need a tree control that allows the user to select multiple items at a time, but this feature is not provided by the standard common controls. Thanks to Richard Hazlewood's great article, this feature has been implemented nicely. However, Richard's implementation only supports the simple style rubber band selection. What I want to have is a tree control that implements an alpha-blended selection rectangle (just like explorer does).

Eugen Podsypalnikov did give us an approach to that with his CCoverWnd class, but the focus issue and CWnd derived implementation makes me think that maybe implementing the selection drawing by the tree control itself would be a better idea, so here comes the CMultiSelTriCheckTreeCtrl class in MFC.

The demo project actually belongs to my another humble article CVComboBox, so the download URLs are shared here.

As the snapshot shown, the tree control can have tri-states checkboxes display for each item, and all the selected items will be checked/unchecked when you click the checkbox of one of them. If you want to only check/uncheck the very item which is being selected, you can click the checkbox while holding the control key down.

MulSelTree.png

MulSelTree.gif

Interfaces of CMultiSelTriCheckTreeCtrl

CMultiSelTriCheckTreeCtrl is an MFC wrapper class that encapsulates the multi-select tree control, it derives from another MFC wrapper class called CTriCheckStateTreeCtrl, which implements a tri-check state tree control.

The interfaces of CMultiSelTriCheckTreeCtrl are quite similar to those of CMultiTree by Richard Hazlewood since I just simply changed the selection drawing code after all, here are the public interfaces:

C++
inline BOOL IsMultiSelectable() const ;

void  SetMultiSelectable(BOOL bMultiSel = TRUE);

inline BOOL IsSelected(HTREEITEM hItem) const;

size_t  GetSelectedCount() const;
HTREEITEM GetFirstSelectedItem() const;
HTREEITEM GetNextSelectedItem(HTREEITEM hItem) const;
HTREEITEM GetPrevSelectedItem(HTREEITEM hItem) const;

void  SelectAll(BOOL bSelect = TRUE);
void  SelectRange(HTREEITEM hFirst, HTREEITEM hLast, BOOL bOnly = TRUE);

//Note: not virtual, so must call this class (or derivative)
BOOL  SetItemState(HTREEITEM hItem, UINT nState, UINT nStateMask);
UINT  GetItemState(HTREEITEM hItem, UINT nStateMask) const;

virtual void ToggleCheckSelectedItem();
virtual void DeleteSelectedItem();

void  GetSelectedList(TreeItemList& selectedList) const;

The Basic Steps to Use CMultiSelTriCheckTreeCtrl in a Dialog Based Application

Here are the basic steps to show how to use the class CMultiSelTriCheckTreeCtrl:

  1. Create a dialog based MFC project called CMultiSelTreeDemo.
  2. Add the following source files (under the folder code_base) into your workspace:
    • CustomDrawCommon.cpp
    • CustomDrawCommon.h
    • CustomDrawControl.cpp
    • CustomDrawControl.h
    • CustomDrawUtils.cpp
    • CustomDrawUtils.h
  3. Open the precompiled header file, which is normally StdAfx.h, append this line to it:
    C++
    #include "..\code_base\CustomDrawCommon.h"
  4. If you are using Visual Studio 6.0, you also need to put these at the beginning of StdAfx.h:
    C++
    #pragma warning(disable: 4786)  // try to disable the annoying warning in VC6
    
    #ifndef WINVER
     #define WINVER 0x0501
    #endif // WINVER
    
    #ifndef _WIN32_WINNT
     #define _WIN32_WINNT 0x0501
    #endif // _WIN32_WINNT
  5. Open the dialog with resource editor, drag and drop a tree control from the control toolbar to the dialog.
  6. Add a corresponding control member variable to that tree control, name it like m_myTreeCtrl, the IDE will add the necessary code for you, it would look like:
    C++
    CTreeCtrl m_myTreeCtrl;
  7. Open the header file of the dialog class, put the #include directive to the beginning of it like this:
    C++
    #include "..\code_base\CustomDrawControl.h"
  8. Rename the type of m_myTreeCtrl from CTreeCtrl to CMultiSelTriCheckTreeCtrl.

History

  • 2010-12-29: Initial release

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
China China
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionProblem visual c++ 2005 error C2011 redefinition de type enum Pin
bougnat_8320-Mar-20 2:36
bougnat_8320-Mar-20 2:36 
GeneralMy vote of 5 Pin
Member 125249613-Jun-16 5:10
Member 125249613-Jun-16 5:10 
GeneralMy vote of 5 Pin
yulingfeng21-Apr-13 16:29
yulingfeng21-Apr-13 16:29 
GeneralMy vote of 5 Pin
Matth Moestl13-Dec-12 0:44
professionalMatth Moestl13-Dec-12 0:44 
QuestionTreeCtrl MultiSelection Issue Pin
ReneG21-Feb-12 3:45
ReneG21-Feb-12 3:45 
AnswerRe: TreeCtrl MultiSelection Issue Pin
Geraldo Brodbeck15-May-19 7:39
Geraldo Brodbeck15-May-19 7:39 
GeneralMy vote of 5 Pin
DreamSoft.ps13-Jan-11 0:33
DreamSoft.ps13-Jan-11 0:33 
GeneralMy vote of 5 Pin
skyformat99@gmail.com12-Jan-11 20:01
skyformat99@gmail.com12-Jan-11 20:01 
Generalnice Pin
BillW337-Jan-11 6:50
professionalBillW337-Jan-11 6:50 
GeneralMy vote of 5 Pin
Wym24-Jan-11 19:51
professionalWym24-Jan-11 19:51 
GeneralMy vote of 5 Pin
pd964-Jan-11 15:55
pd964-Jan-11 15:55 
GeneralMy vote of 4 Pin
mnjrupp4-Jan-11 6:48
mnjrupp4-Jan-11 6:48 
GeneralMy vote of 4 Pin
SledgeHammer0131-Dec-10 13:21
SledgeHammer0131-Dec-10 13:21 
GeneralRe: My vote of 4 Pin
yonken1-Jan-11 2:46
yonken1-Jan-11 2:46 
GeneralRe: My vote of 4 Pin
SledgeHammer011-Jan-11 13:17
SledgeHammer011-Jan-11 13:17 
GeneralRe: My vote of 4 [modified] Pin
yonken3-Jan-11 6:17
yonken3-Jan-11 6:17 
SledgeHammer01 wrote:
1) No need to search collapsed nodes


Actually GetNextVisibleItem() will automatically skip those collapsed nodes so this has been done implicitly.


SledgeHammer01 wrote:
2) Rectangle is contiguous, so once you find a highlighted node, you can stop once you find the next non highlighted node


That's not true, suppose you drag the selection box on the empty area (which is the space that does not contain any item), all the existing items that were selected should be deselected at the same time, which means we still need to check all the items even if they are not "hilighted" (inside the selection box).


SledgeHammer01 wrote:
3) The *biggest* optimization you can make is only processing the changed area


Seems like we have the same idea, I had put such comment inside the source code, see OnMouseMove() function, but since it's too complicate, I do not intend to do it that way.


SledgeHammer01 wrote:
4) One other optimization, is since all items are the same height, you can do simple math to find the items to select / deselect (or at least "guess" and then check).


See the reason for 1).

I've spent some time to investigated this issue, it turns out that the CPU goes high mostly because I call SetItemState() unconditionally, so I improve the code and now the speed is faster than the previous implementation.

If what we want to have is the same speed compare with Richard's implementation, we might have to drop this alpha-blended selection feature as well since it require more time to draw (this can be comfirmed by comment out the InvalidateRect(rcUpdateSelBox); and UpdateWindow() inside OnMouseMove()). Frown | :( Or of course we might try your suggestion 3, but emh...Unsure | :~

Now I will update the improved source code.

modified on Monday, January 3, 2011 12:46 PM

GeneralRe: My vote of 4 Pin
SledgeHammer013-Jan-11 10:21
SledgeHammer013-Jan-11 10:21 
GeneralRe: My vote of 4 [modified] Pin
yonken4-Jan-11 2:09
yonken4-Jan-11 2:09 
GeneralMy vote of 5 Pin
RaviRanjanKr29-Dec-10 19:36
professionalRaviRanjanKr29-Dec-10 19:36 
GeneralGreat Job, i love it Pin
Roberto Guerzoni29-Dec-10 5:43
professionalRoberto Guerzoni29-Dec-10 5:43 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.