Wednesday, September 30, 2009

TreeViews and Check Boxes

Important side note when trying to insert checked items in to a newly created Win32 TreeView.

From the docs:

If you want to use this style, you must set the TVS_CHECKBOXES style with SetWindowLong after you create the treeview control, and before you populate the tree. Otherwise, the checkboxes might appear unchecked, depending on timing issues.


Good to know. Otherwise you might spend all morning trying to figure out why your inserted items don't appear checked. Also, I saw some confusion on the internet about how to insert a checked item. Witness:


TV_INSERTSTRUCT t = {0};
t.hParent = 0;
t.hInsertAfter = TVI_SORT;
t.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_STATE;
t.item.pszText = "text";
t.item.lParam = 1;
t.item.stateMask = ~0U; // set all state bits
t.item.state = INDEXTOSTATEIMAGEMASK(2); // 2 = checked
TreeView_InsertItem(TreeHwnd, &t);



Easy Peasy.

Another note from the docs:


Once a tree-view control is created with this style, the style cannot be removed. Instead, you must destroy the control and create a new one in its place. Destroying the tree-view control does not destroy the check box state image list. You must destroy it explicitly. Get the handle to the state image list by sending the tree-view control a TVM_GETIMAGELIST message. Then destroy the image list with ImageList_Destroy.



I did this via subclassing my TreeView and catching WM_DESTROY before forwarding it on to the default window procedure:


// Destroy our image list.
HIMAGELIST hCheckImages = TreeView_GetImageList(hwnd, TVSIL_STATE);
ImageList_Destroy(hCheckImages);