Click here to Skip to main content
11,479,412 members (52,797 online)
Click here to Skip to main content

CQuadStateTree

, 2 Dec 2014 CPOL 8.2K 646 22
Rate this:
Please Sign up or sign in to vote.
A CTreeCtrl derived control that has four checkbox states

Quad State Tree Control

Introduction

I was in need of a tree control with several features that are not found in the standard CTreeCtrl:

  1. Checkboxes with indeterminate state. When a tree item's child items are not all in the same state then that item's checkbox should show an indeterminate state.
  2. Setting a parent tree item's checkbox state to checked or unchecked should automatically set all it's child tree item's states to the same state.
  3. Setting a child tree item's checkbox state to checked or unchecked should automatically set it's parent tree item's state to the appropriate state.
  4. Not all the items in the tree need to have a checkboxes. Sometimes the root of the tree just needs to be a labeled place holder.
  5. Notifications. It would be really nice if the parent window of the tree control recieved detailed notification messages when a tree item's checkbox state changes.
  6. Ability to block a change in a checkbox state. When a notification (see above) is recieved by the parent window, it should be possible to block the checkbox state from changing.

Presented in this article is the CQuadStateTree class that delivers all these requirements, plus a few more.

Background

Why Quad State you may ask? It is because each checkbox in the tree control can have four states. Of course there is the basic checked and unchecked, and the familiar indeterminate state. But I have added a forth state which is 'none'. You may say that 'none' is not a state, but it actually is. How else would one specify that a tree item not have a checkbox when the rest of the tree control does have them?

Of course to have the 'none' state make any sense there has to be a basic restriction placed on it. The restriction being that in order for a tree item to have a 'none' state, all of it's parent items up the tree, all the way up to the root, must also be in the 'none' state. It makes no sense to able to select a parent item and not be able to select a child item.

Using the code

The first step for using this code in your own projects is to add the QuadStateTree.h and QuadStateTree.cpp files to your project. Then in any file that needs access to the CQuadStateTree class you just have to #include QuadStateTree.h.

Since CQuadStateTree is derived from CTreeCtrl you can use this class the exact same way you would use CTreeCtrl with the following API exceptions:

CQuadStateTree Data Types

The CQuadStateTree uses the following custom data types.

TVCS_CHECKSTATE

The TVCS_CHECKSTATE enum defines the four possible checkbox states.

Syntax

enum TVCS_CHECKSTATE
{
    TVCS_NONE          = -1,
    TVCS_UNCHECKED     =  0,
    TVCS_CHECKED       =  1,
    TVCS_INDETERMINATE =  2 
};

Members

TVCS_NONE - The tree item has no checkbox associated with it.
TVCS_UNCHECKED - The tree item's checkbox does not have a check mark in it.
TVCS_CHECKED - The tree item's checkbox has a check mark in it.
TVCS_INDETERMINATE - The tree item has child items, and the child items are a mix of checked and unchecked.

NMTVNCHECK

The NMTVNCHECK structure contains information about a change in a tree item's checkbox state.

Syntax

typedef struct tagTVNCHECK    
{
    NMHDR hdr;                     
    HTREEITEM hTreeItem;           
    LPARAM lParam;                 
    TVCS_CHECKSTATE OldCheckState; 
    TVCS_CHECKSTATE NewCheckState; 
    HTREEITEM TriggerItem;         
} NMTVNCHECK, *LPNMTVNCHECK;

Members

hdr - NMHDR structure that contains information about the TVN_CHECK notification message.
hTreeItem - Handle to the tree item whose checkbox is changing state.
lParam - Application specific data that is associated with hTreeItem.
OldCheckState - The old checkbox state for hTreeItem.
NewCheckState - The new checkbox state for hTreeItem.
TriggerItem - Handle to the tree item that was toggled by the user or was specified in a call to SetCheck().

CQuadStateTree notification messages

TVN_CHECK notification code

The TVN_CHECK notification is sent to the parent window as a WM_NOTIFY message to inform the parent that a checkbox is about to change state.

Syntax

TVN_CHECK

    pNMTvnCheck = (LPNMTVNCHECK) lParam

Parameters

pNMTvnCheck - a pointer to a NMTVNCHECK structure.

Return Value

If the hTreeItem and TriggerItem members of the NMTVNCHECK structure are pointing to the same tree item then returning a non-zero value will stop the tree item checkbox from changing.

In all other cases the return value is ignored.


ON_TVN_CHECK Message map macro

Use the ON_TVN_CHECK macro to define an TVN_CHECK notification handler function.

Syntax

ON_TVN_CHECK(<nID>, <pFunction>)

Parameters

nID - Identification number for the tree control
pFunction - Pointer to the member function to be called when the TVN_CHECK notification is sent

Remarks

pFunction must be declared with the following prototype:

afx_msg void memberFxn( NMHDR * pNMHDR, LRESULT * pResult );

where the italicized parameters are:

pNMHDR
A pointer to a NMHDR structure which can be cast to a LPNMTVNCHECK structure pointer.

pResult
A pointer to the result code that you set before you return


CQuadStateTree member functions

CQuadStateTree::CQuadStateTree

Class constructor that is called to construct a CQuadStateTree object.

Syntax

CQuadStateTree();

CQuadStateTree::~CQuadStateTree

Class destructor that is called when a CQuadStateTree object is deleted.

Syntax

virtual ~CQuadStateTree();

CQuadStateTree::GetCheck

Syntax

TVCS_CHECKSTATE GetCheck(
    HTREEITEM hTreeItem) const;

Parameter

hTreeItem - Handle to the tree item to retrieve the checkbox state from.

Return Value

Returns a TVCS_CHECKSTATE enum indicating the current stateof the checkbox.

Remarks

This function is identical to CTreeCtrl::GetCheck. The only difference is that the return value is returned as a TVCS_CHECKSTATE enum instead of a BOOL.


CQuadStateTree::SetCheck

Syntax

BOOL SetCheck (
    HTREEITEM hTreeItem,
    TVCS_CHECKSTATE NewCheckState = TVCS_CHECKED);

Parameters

hTreeItem - Handle to the tree item to recieve the checkbox state change.
NewCheckState - The new checkbox state. By default the the checkbox state is set to TVCS_CHECKED.

Return Value

Nonzero if successful; otherwise zero.

Remarks

SetCheck() will return zero for the following reasons:

  1. NewCheckState is TVCS_INDETERMINATE. The TVCS_INDETERMINATE state will only be set by the control when a tree item's children are in different states. It is not possible to set TVCS_INDETERMINATE via SetCheck().
  2. NewCheckState is TVCS_NONE. The only way to set a checkbox to TVCS_NONE state is if all hTreeItem's parent tree items are already set to TVCS_NONE. To set TVCS_NONE state you have to start at the tree's root item and work your way down.

CQuadStateTree::Create

Call this function to create a control (a child window) and associate it with the CQuadStateTree object.

Syntax

virtual BOOL Create(
    DWORD dwStyle,
    const RECT& rect,
    CWnd* pParentWnd,
    UINT nID);

Parameters

dwStyle - Specifies the tree view control's style. Apply window styles, described in CreateWindow, and any combination of tree view control styles as described in the Platform SDK.
rect - A reference to a RECT structure describing the size and position of the window to be created, in client coordinates of pParentWnd.
pParentWnd - A pointer to the window that is the control's parent.
nID - The control's child-window ID.

CQuadStateTree::CreateEx

Call this function to create a control (a child window) and associate it with the CQuadStateTree object.

Syntax

virtual BOOL CreateEx(
    DWORD dwExStyle,
    DWORD dwStyle,
    const RECT& rect,
    CWnd* pParentWnd,
    UINT nID);

Parameters

dwExStyle - Specifies the extended style of the control being created. For a list of extended Windows styles, see the dwExStyle parameter for CreateWindowEx in the Platform SDK.
dwStyle - Specifies the tree view control's style. Apply window styles, described in CreateWindow, and any combination of tree view control styles as described in the Platform SDK.
rect - A reference to a RECT structure describing the size and position of the window to be created, in client coordinates of pParentWnd.
pParentWnd - A pointer to the window that is the control's parent.
nID - The control's child-window ID.

Remarks

I have not explored the tree view extended styles, so I have no idea how they will influence this control.


Deriving from CQuadStateTree

CQuadStateTree has to handle several different messages in order to work properly. If you derive your own control from CQuadStateTree and you handle the same messages in derived class, be sure to call the CQuadStateTree message handler functions from your message handler functions.

Listed here is the messages that CQuadStateTree handles and the name of the functions that handle them:

NM_CLICK CQuadStateTree::OnNMClick(NMHDR *pNMHDR, LRESULT *pResult)
NM_TVSTATEIMAGECHANGING CQuadStateTree::OnNMTvStateImageChanging(NMHDR *pNMHDR, LRESULT *pResult)
TVN_KEYDOWN CQuadStateTree::OnTvnKeydown(NMHDR *pNMHDR, LRESULT *pResult)
TVN_ITEMCHANGED CQuadStateTree::OnTvnItemchanged(NMHDR *pNMHDR, LRESULT *pResult)
TVM_SETITEM CQuadStateTree::OnTvmSetitem(WPARAM wp, LPARAM lp)

History

November 28, 2014 - Initial Release

License

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

Share

About the Author

PJ Arends
President
Canada Canada
No Biography provided

Comments and Discussions

 
General5 !! Pin
GuyM1-Dec-14 21:28
memberGuyM1-Dec-14 21:28 
GeneralRe: 5 !! Pin
PJ Arends1-Dec-14 22:34
professionalPJ Arends1-Dec-14 22:34 
GeneralMy vote of 5 Pin
Volynsky Alex30-Nov-14 10:48
professionalVolynsky Alex30-Nov-14 10:48 
GeneralRe: My vote of 5 Pin
PJ Arends1-Dec-14 10:30
professionalPJ Arends1-Dec-14 10:30 
GeneralRe: My vote of 5 Pin
Volynsky Alex1-Dec-14 10:41
professionalVolynsky Alex1-Dec-14 10:41 
GeneralMy vote of 5 Pin
Franc Morales28-Nov-14 10:42
memberFranc Morales28-Nov-14 10:42 
GeneralRe: My vote of 5 Pin
PJ Arends28-Nov-14 19:26
professionalPJ Arends28-Nov-14 19:26 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.150520.1 | Last Updated 2 Dec 2014
Article Copyright 2014 by PJ Arends
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid