TreeView 控件会泄漏正常的 ImageList 但 ListView 控件不会?

TreeView Control will leak normal ImageList but ListView control doesn't?

我正在使用任务管理器查看我动态创建的控件,发现每次我创建一个带有 ImageList 的 TreeView 时,GDI 对象 计数每次都会增加 4我摧毁了这棵树并再次创造。但是,ListView 从来没有问题。

我知道状态图像的 TVS_CHECKBOXES 问题并且已经破坏了状态图像列表,但我随后实施了:

ImageList_Destroy(TreeView_SetImageList(GetHandle(), nullptr, TVSIL_NORMAL));

现在资源泄漏已经消失了。

到目前为止,您似乎必须手动清理 WM_DESTROY 中的以下图像:

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.

但是 ListView 是不同的,是设计使然还是我应该在 WM_DESTROY 中继续使用类似的东西:

ImageList_Destroy(ListView_SetImageList(GetHandle(), nullptr, LVSIL_STATE));
ImageList_Destroy(ListView_SetImageList(GetHandle(), nullptr, LVSIL_SMALL));
ImageList_Destroy(ListView_SetImageList(GetHandle(), nullptr, LVSIL_NORMAL));

请注意,使用 WM_NCDESTROY 对 TreeView 来说太晚了。

这两个控件在这方面不一致

树控件不拥有您提供给它的图像列表的所有权,因此您仍然负责释放它。

列表视图控件取得所有权,除非您设置了LVS_SHAREIMAGELISTSwindow样式。

注意树控件也有一个related quirk;如果您设置了 TVS_CHECKBOXES 样式,即使您没有创建状态图像列表,您也有责任释放它。

您看到的是有记录的行为。

对于 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.

以及:

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 a TVM_GETIMAGELIST message. Then destroy the image list with ImageList_Destroy.

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.

与 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.