Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / MFC

A Multi-selectable Tree Control Supports Transparent Selection Rectangle

4.68/5 (36 votes)
29 Dec 2010CPOL2 min read 210.8K   8.9K  
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)