更改 TVS_CHECKBOXES 使用的 ImageList 会导致资源泄漏吗?
Can changing ImageList used by TVS_CHECKBOXES cause resource leak?
Win32:
创建树控件并将样式更改为 TVS_CHECKBOXES,然后 TVSIL_STATE 的 ImageList 更改为自定义 ImageList,您是否需要删除返回的先前 ImageList 或它是一个共享资源,不应该。
MFC:
由于存在对象层次结构,在这种情况下,您不知道 CImageList 是否正在替换系统提供的对象或来自父对象之一的对象 类。在那种情况下,正确的处理方法是什么?对于 ImageLists,你可以 CImageList::Attach()
、CTreeCtrl::SetImageList()
、CImageList::Detach()
然后 CTreeCtrl::OnDestroy()
继续 CImageList *pil=CTreeCtrl::SetImageList(NULL, TVSIL_STATE)
然后 pil->DeleteImageList()
,但是对象呢? ,我们应该改为 delete pil
吗?或者我们是否总是需要设置一个成员变量,即图像列表,然后 CTreeCtrl::SetImageList()
更改它然后 OnDestroy()
放回旧的或者只是将其设置为 NULL?
Can changing ImageList used by TVS_CHECKBOXES cause resource leak?
是的。来自 Tree-View Control Window Styles:
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
.
奖金"Old New Thing"link:Beware of the leaked image list when using the TVS_CHECKBOXES style
Win32 解决方案
我们可以利用 TVM_SETIMAGELIST
(由 TreeView_SetImageList()
包装)returns 上一个图像列表的句柄。
HIMAGELIST hNewImageList = ImageList_Create(/* insert arguments */);
HIMAGELIST hOldImageList = TreeView_SetImageList( hwndTreeView, hNewImageList, TVSIL_STATE );
if( hOldImageList ) // a good habit, to check if handle is not NULL
{
ImageList_Destroy( hOldImageList );
hOldImageList = NULL;
}
树形控件销毁后,您还必须ImageList_Destroy
新的图像列表。
MFC 解决方案
MFC 并没有太大的不同,我。 e.它不会自动清理由 TVS_CHECKBOXES
样式创建的图像列表。
在承载树控件的 class 的声明中创建一个成员变量 CImageList m_newImageList;
(例如 CDialog
派生的 class)。这确保新图像列表的生命周期不会在树控件 window 之前结束,并通过其析构函数自动销毁图像列表。
m_newImageList.Create(/* insert arguments */);
CImageList* pOldImageList = m_treeCtrl.SetImageList( &m_newImageList, TVSIL_STATE );
if( pOldImageList )
{
pOldImageList->DeleteImageList();
pOldImageList = nullptr;
}
CTreeCtrl::SetImageList()
returns 指向临时对象的指针(通过 CImageList::FromHandle()
),该对象不拥有它包装的句柄。您必须 DeleteImageList()
以避免资源泄漏,但绝不能 delete
返回由 SetImageList
返回的指针。 MFC 在空闲处理期间自动清理临时对象(CWinApp::OnIdle()
)。
进一步阅读:
- TN003: Mapping of Windows Handles to Objects。
- What is the lifetime of a CWnd obtained from CWnd::FromHandle?
(将
CWnd
替换为CImageList
,MFC的FromHandle()
方法class都是一样的。
Win32:
创建树控件并将样式更改为 TVS_CHECKBOXES,然后 TVSIL_STATE 的 ImageList 更改为自定义 ImageList,您是否需要删除返回的先前 ImageList 或它是一个共享资源,不应该。
MFC:
由于存在对象层次结构,在这种情况下,您不知道 CImageList 是否正在替换系统提供的对象或来自父对象之一的对象 类。在那种情况下,正确的处理方法是什么?对于 ImageLists,你可以 CImageList::Attach()
、CTreeCtrl::SetImageList()
、CImageList::Detach()
然后 CTreeCtrl::OnDestroy()
继续 CImageList *pil=CTreeCtrl::SetImageList(NULL, TVSIL_STATE)
然后 pil->DeleteImageList()
,但是对象呢? ,我们应该改为 delete pil
吗?或者我们是否总是需要设置一个成员变量,即图像列表,然后 CTreeCtrl::SetImageList()
更改它然后 OnDestroy()
放回旧的或者只是将其设置为 NULL?
Can changing ImageList used by TVS_CHECKBOXES cause resource leak?
是的。来自 Tree-View Control Window Styles:
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 withImageList_Destroy
.
奖金"Old New Thing"link:Beware of the leaked image list when using the TVS_CHECKBOXES style
Win32 解决方案
我们可以利用 TVM_SETIMAGELIST
(由 TreeView_SetImageList()
包装)returns 上一个图像列表的句柄。
HIMAGELIST hNewImageList = ImageList_Create(/* insert arguments */);
HIMAGELIST hOldImageList = TreeView_SetImageList( hwndTreeView, hNewImageList, TVSIL_STATE );
if( hOldImageList ) // a good habit, to check if handle is not NULL
{
ImageList_Destroy( hOldImageList );
hOldImageList = NULL;
}
树形控件销毁后,您还必须ImageList_Destroy
新的图像列表。
MFC 解决方案
MFC 并没有太大的不同,我。 e.它不会自动清理由 TVS_CHECKBOXES
样式创建的图像列表。
在承载树控件的 class 的声明中创建一个成员变量 CImageList m_newImageList;
(例如 CDialog
派生的 class)。这确保新图像列表的生命周期不会在树控件 window 之前结束,并通过其析构函数自动销毁图像列表。
m_newImageList.Create(/* insert arguments */);
CImageList* pOldImageList = m_treeCtrl.SetImageList( &m_newImageList, TVSIL_STATE );
if( pOldImageList )
{
pOldImageList->DeleteImageList();
pOldImageList = nullptr;
}
CTreeCtrl::SetImageList()
returns 指向临时对象的指针(通过 CImageList::FromHandle()
),该对象不拥有它包装的句柄。您必须 DeleteImageList()
以避免资源泄漏,但绝不能 delete
返回由 SetImageList
返回的指针。 MFC 在空闲处理期间自动清理临时对象(CWinApp::OnIdle()
)。
进一步阅读:
- TN003: Mapping of Windows Handles to Objects。
- What is the lifetime of a CWnd obtained from CWnd::FromHandle?
(将
CWnd
替换为CImageList
,MFC的FromHandle()
方法class都是一样的。