Method 1: Using the TVS_CHECKBOXES style
There are two ways to use the TVS_CHECKBOXES style with the TTreeView component. One approach is to create a TTreeView descendant class, then augment the CreateParams() method, and then add TVS_CHECKBOXES to the Style data member of the method’s TCreateParams-type parameter. Another approach is to use to the GetWindowLong() and SetWindowLong() API functions to add the TVS_CHECKBOXES to an existing TTreeView object.
For simplicity, I’ll demonstrate the latter approach; however, keep in mind that, by using this approach, after the TVS_CHECKBOXES style is set you must not execute any code that causes the TTreeView object’s underlying tree-view control to be recreated (e.g., by changing the TreeView’s Ctl3D or BorderStyle property, or by recreating the TreeView’s parent control); I’ll explain why shortly.
For this example, Form1 contains a single TTreeView object (TreeView1) as depicted in Figure A. Here’s the code to add the TVS_CHECKBOXES style:
...
When the TVS_CHECKBOXES style is set, the tree-view control creates an image list to which it adds three bitmaps: a placeholder bitmap (stored in the first position), and two additional bitmaps containing images of unchecked and checked check boxes (stored in the second and third positions, respectively). This image list is then used as the tree-view’s state image list. Recall that a tree-view’s state image list is optionally used display an additional glyph next to each tree node (see the TTreeView::StateImages property).
...
Again, the state image list (which is created by setting the TVS_CHECKBOXES style) must be destroyed whenever the tree-view is destroyed. For this reason, when you use the TVS_CHECKBOXES style with an existing TTreeView object, you must avoid code that causes the underlying tree-view to be recreated. Alternatively, you could use the FreeStateImageList() function immediately before executing the code that recreates the tree-view. Also note that if you use the TVS_CHECKBOXES style in a TTreeView descendant class, you should destroy the state image list in response to the WM_DESTROY message.
Listing A contains a few of utility functions that can be used to manipulate each node’s check box. For example, to manually check the selected node’s check box, you’d call SetNodeCheckState() like so:
SetNodeCheckState(
*TreeView1->Selected, tcChecked
);
Similarly, to remove a node’s check box, you’d call SetNodeCheckState(), specifying tcNone as the second parameter. Note that in newer versions of C++Builder, you can use alternatively use the TreeView_GetCheckState() and TreeView_SetCheckState() macros, which are defined in COMMCTRL.H.
Method 2: Using the StateImages property
Although by using the TVS_CHECKBOXES style, the tree-view handles the work of updating each node’s check box, there’s no simple way to adjust the appearance or the size of the check boxes (you’d have to manipulate the state image list manually). Fortunately, by using the TTreeView::StageImages property, you can avoid the TVS_CHECKBOXES style altogether.
Figure B depicts the ImageList Editor dialog of StateImageList, a TImageList object that will serve as TreeView1’s state image list. Similar to the state image list that’s created by specifying the TVS_CHECKBOXES style, StateImageList contains three bitmaps: a blank, placeholder bitmap, and two custom check-box bitmaps which I screen-captured from a GNOME desktop. Now, instead of using the TVS_CHECKBOXES style, all that’s required is to assign StateImageList to TreeView1’s StateImages property at design time. Furthermore, there’s no need to explicitly call the ImageList_Destroy() function; this is done automatically by the TCustomImageList class.
...