I was using task manager to watch my dynamically created controls and found each time I'd create a TreeView with an ImageList, the GDI objects count would increase by 4 each time I destroyed the tree and created again. However, a ListView never had a problem.
I know of the TVS_CHECKBOXES
issues with the state images and was already destroying of the state imagelist, but I then implemented:
ImageList_Destroy(TreeView_SetImageList(GetHandle(), nullptr, TVSIL_NORMAL));
and now the resource leak is gone.
So far it looks like you have to manually clean up images in WM_DESTROY
for the following:
Button_SetImageList() - Have to set it to switch it to `BUTTON_IMAGELIST.himl=BCCL_NOGLYPH` to clear it.
TreeView_SetImageList(LVILS_STATE) - if you set it or used `TVS_CHECKBOXES`
TreeView_SetImageList(LVILS_NORMAL) - if you set it
BM_SETIMAGE and STM_SETIMAGE - destroy your own but also set to NULL and destroy returned handle to get rid of potential hidden bitmap handle if different handle than your own.
But a ListView is different, is that by design or should I just go ahead in WM_DESTROY
with something like:
ImageList_Destroy(ListView_SetImageList(GetHandle(), nullptr, LVSIL_STATE));
ImageList_Destroy(ListView_SetImageList(GetHandle(), nullptr, LVSIL_SMALL));
ImageList_Destroy(ListView_SetImageList(GetHandle(), nullptr, LVSIL_NORMAL));
Note that using WM_NCDESTROY
is too late for TreeViews.
What you are seeing is documented behavior.
For a TreeView:
TVM_SETIMAGELIST message
TreeView_SetImageList macro
The tree-view control will not destroy the image list specified with this message. Your application must destroy the image list when it is no longer needed.
As well as:
Tree-View Control Window Styles
Constant Description TVS_CHECKBOXES Version 4.70. Enables check boxes for items in a tree-view control. A check box is displayed only if an image is associated with the item. When set to this style, the control effectively uses DrawFrameControl to create and set a state image list containing two images. State image 1 is the unchecked box and state image 2 is the checked box. Setting the state image to zero removes the check box altogether. For more information, see Working with state image indexes.
Version 5.80. Displays a check box even if no image is associated with the item. 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 aTVM_GETIMAGELIST
message. Then destroy the image list withImageList_Destroy
.
If you want to use this style, you must set theTVS_CHECKBOXES
style withSetWindowLong
after you create the treeview control, and before you populate the tree. Otherwise, the checkboxes might appear unchecked, depending on timing issues.
Compared to a ListView:
LVM_SETIMAGELIST message
ListView_SetImageList macro
The current image list will be destroyed when the list-view control is destroyed unless the
LVS_SHAREIMAGELISTS
style is set. If you use this message to replace one image list with another, your application must explicitly destroy all image lists other than the current one.