从存储在 CTreeCtrl 的 LPARAM 中的结构中检索地址/指针 (IXMLDOMNode*) - 不起作用

Retrieving address/pointer (IXMLDOMNode*) from struct stored in LPARAM of CTreeCtrl - not working

本文关键字:IXMLDOMNode 指针 不起作用 检索 存储 CTreeCtrl LPARAM 结构 地址      更新时间:2023-10-16

在自定义CTreeCtrl类中,我LPARAM添加一个指向自定义结构>的指针,其中包含指向IXMLDOMNode*的地址。

稍后,我想从LPARAM中获取指针,并将其中的地址投射回IXMLDOMNode*

只要我在同一范围/函数中使用它(仅在函数中测试),就可以正常工作。当我在其他函数/类中使用它来检索指针并将包含的地址转换为IXMLDOMNode*它是正确的给定地址时。问题是,当我尝试使用它的功能时(例如 get_nodeName(BSTR *name) ) 它会引发未经处理的异常。

Unhandled exception at 0x6522b1b8 in Program.exe: 0xC0000005: Access violation reading location 0x00000000.

插入:

HTREEITEM InsertIntoTree(CustomTreeCtrl &xCtrl, const HTREEITEM hCurrent, CComPtr<IXMLDOMNode> &cpCurrent)
{
    TVINSERTSTRUCT tvItem = {0};
    //[...]
    //tvItem.item.mask has TVIF_PARAM && other flags set...
    tvItem.item.lParam = TreeItemData(cpCurrent, 0).Alloc()->Address();
    //[...]
}

Get (CustomTreeCtrl 中的测试位置):

else
{
    TreeItemData *tiData = TreeItemData::GetPointer(GetItemData(m_hActiveItem)); //Fine
    CComPtr<IXMLDOMNode> F = tiData->GetCComPtr(); //Fine
    BSTR Name = nullptr;
    F->get_nodeName(&Name); //Unhandled Exception
}

结构:

struct TreeItemData
{
    //[...]
    TreeItemData(CComPtr<IXMLDOMNode> &pNode, DWORD dwFlags)
    {
        m_dwCComPtrAddress  =   reinterpret_cast<DWORD>(&*pNode);
        m_dwFlags           =   dwFlags;
    }
    CComPtr<IXMLDOMNode> GetCComPtr(void)
    {
        return CComPtr<IXMLDOMNode>(reinterpret_cast<IXMLDOMNode*>(m_dwCComPtrAddress));
    }
    TreeItemData *Alloc(void)
    {
        return new TreeItemData(*this);
    }
    LPARAM Address(void)
    {
        return reinterpret_cast<LPARAM>(&*this);
    }
    static TreeItemData *GetPointer(DWORD Address)
    {
        return reinterpret_cast<TreeItemData*>(Address);
    }
    //[...]
    DWORD m_dwCComPtrAddress;
    DWORD m_dwFlags;
};

问:可能有什么问题?如何让我的工作指针返回IXMLDOMNode

  1. 如果您有指针,请始终使用 DWORD_PTR。只是为了64位兼容性。
  2. COM 指针使用引用计数。CComPtr 关心这个参考计数。将 CComPtr 传递给结构。您可以在不增加引用计数的情况下从 CComPtr 中获取对象指针。因此,当您尝试使用它时,您的对象可能已经被销毁,因为 CComPtr 已经被销毁了。

还要在 TreeItemData 结构中使用智能指针。这还可以确保在释放树项结构时释放对象。

警告:您知道,当您从 CTreeCtrl 中删除树项时,您必须释放所有这些结构。