Adding Simple Checkbox for each Item


You can check items in a treeview control by using either an overlay image or a couple of state images. Both the techniques are fairly simple, but using a state image allows us to show a checkbox and makes it obvious to the user.

In this section we allow an item to have only two states. Either it is checked or it is not. For a tree this is not always the best choice. We may also want imformation as to whether any of the child or descendant items are checked or not. We will cover that in the next topic.

Step 1: Create bitmap with checkbox images

Create a bitmap with an image of an unchecked checkbox and an image with a checked checkbox. Since we will be using this bitmap for the state image list, the first image will not be used. So the sequence of images in the bitmap is - blank image, empty checkbox and checked checkbox.


Step 2: Initialize the state image list

Setting up state images has been covered in a previous topic. If the tree control class has a member variable m_imageState then here's how to set the image list.
	m_tree.m_imageState.Create( IDB_STATE, 13, 1, RGB(255,255,255) );
	m_tree.SetImageList( &(m_tree.m_imageState), TVSIL_STATE );

Step 3: Insert items with the checkbox as a state image

If you are using TV_INSERTSTRUCT to insert an item into the tree control, then specify the state and the stateMask in the TV_ITEM member. The index of the state image is specified by using the macro INDEXTOSTATEIMAGEMASK. You can also use the SetItemState() function.

SetItemState( hItem, INDEXTOSTATEIMAGEMASK(1), TVIS_STATEIMAGEMASK );

Step 4: Add code to OnLButtonDown to toggle checkbox

When the user clicks on the checkbox, then the checkbox state has to be toggled. We use the HitTest() function to determine if the click was on the checkbox. When we get the state image index to determine whether the item is checked or not, the GetItemState() function returns the value in the form used internally by the tree control. Shifting the value by 12 bit places to the right gives us the proper index value. We then toggle the state of the item.
void CTreeCtrlX::OnLButtonDown(UINT nFlags, CPoint point) 
{
	UINT uFlags=0;
	HTREEITEM hti = HitTest(point,&uFlags);

	if( uFlags & TVHT_ONITEMSTATEICON )
	{
		int iImage = GetItemState( hti, TVIS_STATEIMAGEMASK )>>12;
		SetItemState( hti, INDEXTOSTATEIMAGEMASK(iImage == 1 ? 2 : 1), 
					TVIS_STATEIMAGEMASK );
		return;
	}
}

Step 5: Add code to OnKeyDown to toggle checkbox

This step provides the keyboard interface for checking and unchecking an item. The key used is usually the space key, so we will use the space key. The code is nearly the same as in the previous step. Instead of using HitTest() to determine the item handle, we use the function GetSelectedItem().
void CTreeCtrlX::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	if( nChar == VK_SPACE )
	{
		HTREEITEM hti = GetSelectedItem();
		int iImage = GetItemState( hti, TVIS_STATEIMAGEMASK )>>12;
		SetItemState( hti, INDEXTOSTATEIMAGEMASK(iImage == 1 ? 2 : 1),
					TVIS_STATEIMAGEMASK );
		return;
	}
}

Step 6: Define helper functions

Define helper functions to determine whether an item is checked or not and to iterate through the checked items. The purpose of the functions is very clear from the function names.
BOOL CTreeCtrlX::IsItemChecked(HTREEITEM hItem)
{
	return GetItemState( hItem, TVIS_STATEIMAGEMASK )>>12 == 2;
}

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

	return NULL;
}

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

	return NULL;
}

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

	return NULL;
}



Comments

  • good control

    Posted by jiqiubo on 03/18/2008 03:59am

    good . thank you.

    Reply
  • IS it possible to add check to fet tree items instead of all.

    Posted by Legacy on 11/18/2003 12:00am

    Originally posted by: Shiv Kumar

    This article shows how to add check box to each tree item. IS it possible to add check to fet tree items instead of all.If yes please let me know.
    Thanks
    Shiv

    Reply
  • Adding check boxes to a CTreeCtrl

    Posted by Legacy on 04/22/2002 12:00am

    Originally posted by: David Orr

    Hi!

    Do you have any suggestions how I might add check boxes to
    a CTreeCtrl. It turns out that the LButtonDown message
    is not sent for the control and the message provided (NM_CLICK) does not have mouse coordinates from which to
    perform the HitTest. I've tried GetMessagePos(), but its coordindates are not something HitTest likes. This is true even after converting to client coordinates with ScreenToClient().

    Any hint would be greatly appreciated.

    David

    Reply
  • initializing Tree Control checkboxes

    Posted by Legacy on 12/31/2000 12:00am

    Originally posted by: Oren

    While opening a dialog with CTreeCtrl using check boxes,
    I have initalized the CTreeCtrl object in the OnInitDailog
    virtual function.
    Unfotunately somewhere in the middle of the DoModal on the
    DialogBox the state of the check boxes was changed to unchecked ...
    While trying to change the checkbox in other places in the program - it works ...

    If you know what could cause such a problem - i'wd be most thankfull.

    Reply
  • Check Tree Control

    Posted by Legacy on 10/03/2000 12:00am

    Originally posted by: Ashley Frieze

    On my copy of Visual C++ (6), there are functions SetCheck and GetCheck of CTreeCtrl. In addition, there is a Checkboxes style of a tree control.

    I'm not sure if these are new features, but they certainly render this article obsolete.

    Reply
  • Using State Images

    Posted by Legacy on 08/18/1999 12:00am

    Originally posted by: Emendeep Singh

    How to use State Images

    Reply
  • Passing Control to parent class

    Posted by Legacy on 03/10/1999 12:00am

    Originally posted by: George kalash

    CTreeCtrlX::OnLButtonDown is not passing control to its parent class
    
    

    if a tree node do not have TVHT_ONITEMSTATEICON the method is not passing control to its parent method

    I think that the method should be as follows

    if( uFlags & TVHT_ONITEMSTATEICON )
    {
    .....
    .....
    return;
    }

    CTreeCtrl::OnLButtonDown(nFlags, point);

    the same thing applies for OnKeyDown

    thanks
    George Kalash

    Reply
  • Compilation error

    Posted by Legacy on 03/10/1999 12:00am

    Originally posted by: George kalash

    GetNextItem method takes 2 parameters and not one
    
    HTREEITEM GetNextItem( HTREEITEM hItem, UINT nCode );

    GetPrevItem() does not exist under CTreeCtrl we have instead
    HTREEITEM GetPrevSiblingItem( HTREEITEM hItem );

    are these methods specific for CTreeCtrlX?

    thanks
    George Kalash

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • As virtualization becomes the norm throughout organizations of nearly all sizes, and as more organizations look to private cloud solutions, IT decision makers are increasingly in need of ways to keep storage costs and complexity under control in the face of often-runaway virtual machine (VM) sprawl. Application-aware storage is designed to help achieve these important goals. Read this white paper to learn how application-aware storage allows you to gain VM-level visibility into application performance and …

  • According to a 2014 Javelin Strategy & Research Study, there is a new victim of fraud every two seconds – and that's just in the U.S. With identity theft and consumer fraud rising, and more frequent and sizable data breaches in the news, financial institutions need to work harder than ever to protect their customers and their business. Download this white paper to learn how you can use multi-channel communications to minimize the costs of fraud while also increasing customer loyalty.

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date