更改TVS_CHECKBOXES使用的ImageList会导致资源泄漏吗?

时间:2018-12-18 05:55:27

标签: winapi mfc imagelist

Win32:

在创建树控件并将样式更改为TVS_CHECKBOXES,然后将TVSIL_STATE的ImageList更改为自定义ImageList的情况下,您是否需要删除返回的先前ImageList或它是共享资源,而不应该是共享资源。

MFC:

由于存在一个对象层次结构,因此在这种情况下,您不知道CImageList是否要替换系统提供的或来自父类之一的内容。在这种情况下,应如何处理?对于ImageList,是否可以1CImageList::Attach()CTreeCtrl::SetImageList()然后CImageList::Detach()前进,然后依次CTreeCtrl::OnDestroy()CImageList *pil=CTreeCtrl::SetImageList(NULL, TVSIL_STATE),但是对象又如何呢? ,我们应该改为pil->DeleteImageList()吗?还是我们总是需要设置一个成员变量即图像列表,然后delete pil对其进行更改,然后CTreeCtrl::SetImageList()放回旧变量或将其设置为NULL?

1 个答案:

答案 0 :(得分:3)

  

更改TVS_CHECKBOXES使用的ImageList会导致资源泄漏吗?

是的。来自Tree-View Control Window Styles

  

销毁树视图控件不会销毁复选框状态   图片清单。您必须明确销毁它。获取句柄   通过向树视图控件发送TVM_GETIMAGELIST   信息。然后使用ImageList_Destroy销毁图像列表。

奖金“旧事物”链接:Beware of the leaked image list when using the TVS_CHECKBOXES style

Win32解决方案

我们可以利用TVM_SETIMAGELIST(由TreeView_SetImageList()包装)将句柄返回到上一个图像列表这一事实。

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样式创建的图像列表。

在承载树控件的类的声明(例如,CImageList m_newImageList;派生类)的声明中创建成员变量CDialog。这样可以确保新图像列表的生存期不会在树控制窗口的生存期之前结束,并通过其析构函数自动销毁图像列表。

m_newImageList.Create(/* insert arguments */);
CImageList* pOldImageList = m_treeCtrl.SetImageList( &m_newImageList, TVSIL_STATE );
if( pOldImageList )
{
    pOldImageList->DeleteImageList();
    pOldImageList = nullptr;
}

CTreeCtrl::SetImageList()返回一个指向临时对象的指针(通过CImageList::FromHandle()),该临时对象不拥有它包装的句柄。您必须DeleteImageList()以避免资源泄漏,但是绝对不要delete返回的指针上的SetImageList。 MFC在空闲处理期间(在CWinApp::OnIdle()中自动清除临时对象。

进一步阅读: