我正在用MFC做一个可插入图片的richedit控件,父类是CRichEdit(richedit2.0),使用IRichEditOleCallback接口插入图片,其中插入图片的函数中使用了这个接口:OleCreateFromFile(clsid, filename,
IID_IOleObject, OLERENDER_DRAW, &formatEtc, 
pClientSite, pStorage, (void**)&pUnk);我单步调试时发现这句所占用的内存,在控件销毁后也不会释放。
其中pClientSite,pStorage我都有调用Release()。
这个控件是要反复插入图片的,而且图片所占空间都很大,所以至少要在控件销毁的时候可以释放内存。插入图片的函数是用MSDN上给的:http://msdn.microsoft.com/en-us/library/dd387916(VS.85).aspx
网上很多例程都是用的类似的函数,但是都没有看到有释放内存的语句(也可能是我看的不够仔细),希望做过类似控件的朋友能给点提示。
最好是可以在删除图片的时候动态释放内存,至少也要在销毁控件的时候释放。

解决方案 »

  1.   

    楼主贴代码,应该可以释放的,原因可能不在pClientSite,pStorage
      

  2.   

    此消息将滚动到插入符号位置文档和位图将滚动到视图中。 若要重复此步骤释放接口指针: 
    if (m_lpObject)
    {
    m_lpObject->Release();
    m_lpObject = NULL;
    }
    if (m_lpStorage)
    {
    m_lpStorage->Release();
    m_lpStorage = NULL;
    }
    if (m_lpClientSite)
    {
    m_lpClientSite->Release();
    m_lpClientSite = NULL;
    }
    最后,释放 m_pRichEditOle。
      

  3.   

    TO 1楼:代码在链接里,我全盘COPY,就是在最后加了这几句:
    pObject->Release();
    pLockBytes->Release();
    pStorage->Release();
    pRichEditOle->Release();TO 2楼:你的代码跟我上面的几句有区别么?我试过了,没有用的,所以暂时不能结贴
      

  4.   

    参考一下:http://support.microsoft.com/kb/220844
      

  5.   

    TO 5楼:这个文档里释放内存的代码就是2楼给的,它里面所有释放的语句我的函数里面也有我最初的设想是在删除图片的同时,就是IRichEditOleCallback::DeleteObject(LPOLEOBJECT lpoleobj)这个接口里释放,但是一直没有找到方法。
    最低限的需求就是要在CRichEditCtrl的析构或OnDestroy()里释放。
      

  6.   

    看到很多人问插入图片的问题,大家做了图片插入以后都没有遇到内存泄露的问题么?
    贴一下插入代码吧:BOOL InsertObject(HWND hRichEdit, LPCTSTR pszFileName)
    {
        HRESULT hr;    // Get the IRichEditOle interface.
        LPRICHEDITOLE pRichEditOle;
        SendMessage(hRichEdit, EM_GETOLEINTERFACE, 0, (LPARAM)&pRichEditOle);
        if (pRichEditOle == NULL)
        {
            return FALSE;
        }    // Create structured storage.
        LPLOCKBYTES pLockBytes = NULL;    hr = CreateILockBytesOnHGlobal(NULL, TRUE, &pLockBytes);
        if (FAILED(hr))
        {
            return FALSE;
        }    LPSTORAGE pStorage;
        hr = StgCreateDocfileOnILockBytes(pLockBytes,
            STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE, 
            0, &pStorage);
        if (FAILED(hr))
        {
            return FALSE;
        }    // Set up data format.
        FORMATETC formatEtc;
        formatEtc.cfFormat = 0;
        formatEtc.ptd = NULL;
        formatEtc.dwAspect = DVASPECT_CONTENT;
        formatEtc.lindex = -1;
        formatEtc.tymed = TYMED_NULL;    // Get an interface to the display site.
        LPOLECLIENTSITE pClientSite;
        hr = pRichEditOle->GetClientSite(&pClientSite);
        if (FAILED(hr))
        {
            return FALSE;
        }    // Create the object and retrieve its IUnknown.
        LPUNKNOWN pUnk;
        CLSID clsid = CLSID_NULL;
        hr = OleCreateFromFile(clsid, pszFileName,
            IID_IUnknown, OLERENDER_DRAW, &formatEtc, 
            pClientSite, pStorage, (void**)&pUnk);
        pClientSite->Release();
        if (FAILED(hr))
        {
            return FALSE;
        }    // Get the IOleObject interface to the object.
        LPOLEOBJECT pObject;
        hr = pUnk->QueryInterface(IID_IOleObject, (void**)&pObject);
        pUnk->Release();
        if (FAILED(hr))
        {
            return FALSE;
        }    // Notify the object that it is contained, so reference counting
        // is done correctly.
        OleSetContainedObject(pObject, TRUE);    // Set up object info.
        REOBJECT reobject = { sizeof(REOBJECT)};
        hr = pObject->GetUserClassID(&clsid);
        if (FAILED(hr))
        {
            pObject->Release();
            return FALSE;
        }
        reobject.clsid = clsid;
        reobject.cp = REO_CP_SELECTION;
        reobject.dvaspect = DVASPECT_CONTENT;
        reobject.dwFlags = REO_RESIZABLE | REO_BELOWBASELINE;
        reobject.dwUser = 0;
        reobject.poleobj = pObject;
        reobject.polesite = pClientSite;
        reobject.pstg = pStorage;
        SIZEL sizel = { 0 };
        reobject.sizel = sizel;    // Move the caret to the end of the text and add a CR.
        SendMessage(hRichEdit, EM_SETSEL, 0, -1);
        DWORD dwStart, dwEnd;
        SendMessage(hRichEdit, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd);
        SendMessage(hRichEdit, EM_SETSEL, dwEnd+1, dwEnd+1);
        SendMessage(hRichEdit, EM_REPLACESEL, TRUE, (WPARAM)L"\n");     // Insert the object.
        hr = pRichEditOle->InsertObject(&reobject);    // Clean up.//我只改了这里,其它和MSDN上给的一样
        pObject->Release();
        pLockBytes->Release();
        pStorage->Release();
        pRichEditOle->Release();     if (FAILED(hr))
        {
            return FALSE;
        }
        return TRUE;
    }
      

  7.   

    所有的GetIRichEditOle都有Release的话就不会有这问题的
      

  8.   

    他会在richedit销毁的时候释放gdi和内存