Click here to Skip to main content
15,867,686 members
Articles / Desktop Programming / MFC

Tree Control with Bitmap Checkboxes Supported

Rate me:
Please Sign up or sign in to vote.
4.69/5 (9 votes)
24 Oct 20023 min read 154.2K   4.7K   38   10
Adding a checkbox along with tree items

Sample Image - new_float.jpg

Introduction

I posted an article for float control several months ago. Somebody gave me a suggestion that I should add a checkbox in my control. I spade for an hour, and I found it is easy to do that. Here is my result. I got up today, "__Stephane Rodriguez__" (fakedwar@hotmail.com) sent me a mail. He suggested to change the title of this article to make it more accurate. Thank you. Anthony_Yio sent me a mail suggesting full selection of children and full un-checking of the children in the tree control as Office 2000 features. I have added the function to my tree control too.  

Bug Fixed

Stephane Rodriguez mentioned a bug in the click and expand of the tree. It is fixed in this version.

Implementation of Custom Tree Control

In the property page of tree control, there is a style named CheckBox. You shall implement your tree control from this point.

Firstly, you shall check CheckBox style in your resource where you want to use checkboxed tree control. Add a new bitmap resource in your project named IDB_STATE which includes 3 images: blank image, unchecked and checked box.

And then, we derive a new class from CTreeControl. Because this sample starts from my previous article, I used the same class as in the previous article. You shall first load the image for state using the following statement:

C++
m_imageState.Create( IDB_STATE, 16, 1, RGB(255,255,255) );
SetImageList( &m_imageState, TVSIL_STATE );

The image will be used together with images for meanings. We shall respond to the Windows' message WM_LBUTTONDOWN to deal with check or uncheck of an item, as follows:

C++
void CXMLTree::OnLButtonDown(UINT nFlags, CPoint point) 
{
   UINT uFlags=0;
   HTREEITEM hti = HitTest(point,&uFlags);

   if( uFlags & TVHT_ONITEMSTATEICON )
   {
      ToggleItemState(hti);

//  int iImage = GetItemState( hti, TVIS_STATEIMAGEMASK )>>12;
//  SetItemState( hti, INDEXTOSTATEIMAGEMASK(iImage == 1 ? 2 : 1), 
//               TVIS_STATEIMAGEMASK );
   return;
   }
   //The following line is needed for our program to run smoothly.
   CTreeCtrl::OnLButtonDown(nFlags, point);
}

In the standard Windows implementation of a control, you shall use space key to toggle the state of check box. So, we need to respond to WM_KEYDOWN for space key.

C++
   if( nChar == VK_SPACE )
   {
      HTREEITEM hti = GetSelectedItem();
      ToggleItemState(hti);
//      int iImage = GetItemState( hti, TVIS_STATEIMAGEMASK )>>12;
//      SetItemState( hti, INDEXTOSTATEIMAGEMASK(iImage == 1 ? 2 : 1), 
//               TVIS_STATEIMAGEMASK );
      return;
   }
   CTreeCtrl::OnKeyDown(nChar, nRepCnt, nFlags);

We add a new function to support full selection of child items. The pros functions are changed to support it. Following is the function added:

C++
void CXMLTree::ToggleItemState(HTREEITEM hti)
{
   int iImage = GetItemState( hti, TVIS_STATEIMAGEMASK )>>12;
   SetItemState( hti, INDEXTOSTATEIMAGEMASK(iImage == 1 ? 2 : 1), 
            TVIS_STATEIMAGEMASK );
   if ( ItemHasChildren(hti))
   {
      HTREEITEM htiChild = this->GetChildItem (hti);
      if (htiChild)
         ToggleItemState(htiChild);
      else
         return ;
      HTREEITEM htiSibling = GetNextSiblingItem (htiChild);
      while (htiSibling )
      {
         ToggleItemState(htiSibling);
         htiSibling = GetNextSiblingItem(htiSibling);
      }
   }
}

We will implement several helper functions to get or set the state of checkbox in the tree control attached to the tree items. If it is check box, it means multiple selection, we shall iterate all items checked. We also provide the function for iteration. But these functions have not been thoroughly tested.

C++
BOOL CXMLTree::IsItemChecked(HTREEITEM hItem)
{
   return GetItemState( hItem, TVIS_STATEIMAGEMASK )>>12 == 2;
}

HTREEITEM CXMLTree::GetFirstCheckedItem()
{
   for ( HTREEITEM hItem = GetRootItem(); 
     hItem!=NULL; hItem = GetNextItem( hItem ) )
      if ( IsItemChecked(hItem) )
         return hItem;

   return NULL;
}

HTREEITEM CXMLTree::GetNextCheckedItem(HTREEITEM hItem)
{
   for ( hItem = GetNextItem( hItem ); 
     hItem!=NULL; hItem = GetNextItem( hItem ) )
      if ( IsItemChecked(hItem) )
         return hItem;

   return NULL;
}

HTREEITEM CXMLTree::GetPrevCheckedItem(HTREEITEM hItem)
{
   for ( hItem = GetPrevItem( hItem ); 
     hItem!=NULL; hItem = GetPrevItem( hItem ) )
      if ( IsItemChecked(hItem) )
         return hItem;

   return NULL;
}

void CXMLTree::SetChecked(HTREEITEM hItem)
{
   SetItemState( hItem, INDEXTOSTATEIMAGEMASK(1), 
                              TVIS_STATEIMAGEMASK );
}
// GetNextItem   - Get next item as if outline was completely expanded
// Returns      - The item immediately below the reference item
// hItem      - The reference item

HTREEITEM CXMLTree::GetNextItem(HTREEITEM hItem)
{
   HTREEITEM   hti;

   if( ItemHasChildren( hItem ) )
      return GetChildItem( hItem ); // return first child
   else{
      // return next sibling item
      // Go up the tree to find a parent's sibling if needed.
      while( (hti = GetNextSiblingItem( hItem )) == NULL ){
         if( (hItem = GetParentItem( hItem ) ) == NULL )
            return NULL;
      }
   }
   return hti;
}

HTREEITEM CXMLTree::GetPrevItem(HTREEITEM hItem)
{
   HTREEITEM hti;

   // Return a previous sibling item if it exists
   if( hti = GetPrevSiblingItem(hItem) )
      return hti;
   else
      // No sibling, return the parent 
      return GetParentItem(hItem);
}

A new function is added to tree control. If you select the item, all of its children are selected. So it is done for uncheck actions. See insertItem function.

Using this new control is very simple. Add a tree control in your dialog box and set the checkbox style. The other operations are same as other controls. Enjoy it!

Acknowledgement

Thanks to Anthony_Yio and Stephane Rodriguez. They gave me good suggestions and bug reports. Thanks to Prettybabe Prettybabe for raising the idea to write such a control.

History

  • October 25th, 2002: Version 1.0
    • Fixed bugs in SetChecked - the state is error
    • Fixed bugs for mouse down to populate nodes
    • Added new functions for full selection and deselection
    • Added new function: SetUnChecked
  • October 24th, 2002: Version 0.9. initial

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.


Written By
Software Developer (Senior)
China China
I'm write program from 1990. My research field is CAG,CAD and Image processing. I select C/C++, ASP, Java, XML as my usaully developing tools. Occasional , write code in Delphi and VB. I'm using Visual C++ from 1996. If you have anything unclear, e-mail to :zhou_cn123@sina.com Software Engineering and CAD is my mainly research program.

You also can reach me on msn: zhoujohnson@hotmail.com

Comments and Discussions

 
Generalwhy i can not open the executable file that show a error messagebox~!! BUG!@#!~ [modified] Pin
golocy24-Apr-09 8:46
golocy24-Apr-09 8:46 
Sleepy | :zzz: The source code is not the same as illustration~~! ! what's that?`
i want to kown how to do a redraw~ how can i to replace the state icon ,i want to replace the checkbox by a bitmap~

Do what want to do,Go where want to go ,nothing is impossible!

modified on Friday, April 24, 2009 2:58 PM

Generalbugs! Pin
thirdwolf27-Jun-05 16:55
thirdwolf27-Jun-05 16:55 
Generaltree control with checkboxes Pin
Member 81356020-Dec-04 18:37
Member 81356020-Dec-04 18:37 
GeneralRe: tree control with checkboxes Pin
Johnson Zhou30-Dec-04 18:38
Johnson Zhou30-Dec-04 18:38 
GeneralC:\Documents and Settings\bala\Desktop\vtree\test_float_control\vs_treectrl\XMLTreeCtrl.cpp(121) : error C2146: syntax error : missing ')' before identifier 'item' Pin
Balkrishna Talele28-Dec-03 23:06
Balkrishna Talele28-Dec-03 23:06 
GeneralAdding Icons to Tree View Pin
Kabini17-Nov-03 21:06
Kabini17-Nov-03 21:06 
Generalicons for items of tree control Pin
sarasara098765411-Oct-03 5:07
sarasara098765411-Oct-03 5:07 
GeneralOffice 2000 installer Pin
Anthony_Yio24-Oct-02 17:48
Anthony_Yio24-Oct-02 17:48 
GeneralRe: Office 2000 installer Pin
Jordan Walters10-Mar-04 12:17
Jordan Walters10-Mar-04 12:17 
GeneralNot very usefull Pin
Neville Franks24-Oct-02 11:48
Neville Franks24-Oct-02 11:48 

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.