我正在用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
网上很多例程都是用的类似的函数,但是都没有看到有释放内存的语句(也可能是我看的不够仔细),希望做过类似控件的朋友能给点提示。
最好是可以在删除图片的时候动态释放内存,至少也要在销毁控件的时候释放。
IID_IOleObject, OLERENDER_DRAW, &formatEtc,
pClientSite, pStorage, (void**)&pUnk);我单步调试时发现这句所占用的内存,在控件销毁后也不会释放。
其中pClientSite,pStorage我都有调用Release()。
这个控件是要反复插入图片的,而且图片所占空间都很大,所以至少要在控件销毁的时候可以释放内存。插入图片的函数是用MSDN上给的:http://msdn.microsoft.com/en-us/library/dd387916(VS.85).aspx
网上很多例程都是用的类似的函数,但是都没有看到有释放内存的语句(也可能是我看的不够仔细),希望做过类似控件的朋友能给点提示。
最好是可以在删除图片的时候动态释放内存,至少也要在销毁控件的时候释放。
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。
pObject->Release();
pLockBytes->Release();
pStorage->Release();
pRichEditOle->Release();TO 2楼:你的代码跟我上面的几句有区别么?我试过了,没有用的,所以暂时不能结贴
最低限的需求就是要在CRichEditCtrl的析构或OnDestroy()里释放。
贴一下插入代码吧: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;
}