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.
CodePudding user response:
The two controls are inconsistent in this regard.
The tree control does not take ownership of the imagelist you give it, so you remain responsible for freeing it.
The listview control does take ownership, unless you set the LVS_SHAREIMAGELISTS
window style.
Note that the tree control also has a related quirk; if you set the TVS_CHECKBOXES
style, you are responsible for freeing the state image list even though you didn't create it.
CodePudding user response:
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.