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_SHAREIMAGELISTS
window样式。
注意树控件也有一个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.
我正在使用任务管理器查看我动态创建的控件,发现每次我创建一个带有 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_SHAREIMAGELISTS
window样式。
注意树控件也有一个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 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.
与 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.