#include <comdef.h>
#include <richedit.h>
#include <richole.h>
#include <OleIdl.h>
class ImageDataObject:IDataObject
{
public:
static void InsertBitmap(IRichEditOle* pRichEditOle,HBITMAP hBitmap);
private:
ULONG m_ulRefCnt;
BOOL m_bRelease;
STGMEDIUM m_stgmed;
FORMATETC m_format;
public:
ImageDataObject():m_ulRefCnt(0)
{
m_bRelease=False;
}
~ImageDataObject()
{
if(m_bRelease)
::ReleaseStgMedium(&m_stgmed);
}
STDMETHOD(QueryInterface)(REFIID iid,void **ppvObject)
{
if(iid==IID_IUnknown||iid==IID_IDataObject)
{
*ppvObject=this;
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
STDMETHOD_(ULONG,AddRef)(void)
{
m_ulRefCnt++;
return m_ulRefCnt;
}
STDMETHOD_(ULONG,Release)(void)
{
if(--m_ulRefCnt==0)
delete this;
return m_ulRefCnt;
}
STDMETHOD(GetData)(FORMATETC *pFormatetc,STGMEDIUM *pMedium)
{
HANDLE hDst;
hDst=::OleDuplicateData(m_stgmed.hBitmap,CF_BITMAP,NULL);
assert(hDst);
pMedium->tymed=TYMED_GDI;
pMedium->hBitmap=(HBITMAP)hDst;
pMedium->pUnkForRelease=NULL;
return S_OK;
}
STDMETHOD(GetDataHere)(FORMATETC *pFormatetc,STGMEDIUM *pMedium)
{
return E_NOTIMPL;
}
STDMETHOD(QueryGetData)(FORMATETC *pFormatetc)
{
return E_NOTIMPL;
}
STDMETHOD(GetCanonicalFormatEtc)(FORMATETC *pFormatetcIn,FORMATETC *pFormatetcOut)
{
return E_NOTIMPL;
}
STDMETHOD(SetData)(FORMATETC *pFormatetc,STGMEDIUM *pMedium,BOOL fRelase)
{
m_format=*pFormatetc;
m_stgmed=*pMedium;
return S_OK;
}
STDMETHOD(EnumFormatEtc)(DWORD dwDirection,IEnumFORMATETC **ppEnumFormatEtc)
{
return E_NOTIMPL;
}
STDMETHOD(DAdvise)(FORMATETC *pFormatetc,DWord dwDvf,IAdviseSink *pAdvSink,
DWORD *pdwConnection)
{
return E_NOTIMPL;
}
STDMETHOD(DUnadvise)(DWORD dwConnection)
{
return E_NOTIMPL;
}
STDMETHOD(EnumDAdvise)(IEnumSTATDATA **ppEnumAdvise)
{
return E_NOTIMPL;
}
void SetBitmap(HBITMAP hBitmap);
IOleObject* GetOleObject(IOleClientSite *pOleClientSite,IStorage *pStorage);
};
void ImageDataObject::InsertBitmap(IRichEditOle *pRichEditOle,HBITMAP hBitmap)
{
SCODE sc;
ImageDataObject *pods=new ImageDataObject;
LPDATAOBJECT lpDataObject;
pods->QueryInterface(IID_IDataObject,(void**)&lpDataObject);
pods->SetBitmap(hBitmap);
IOleClientSite *pOleClientSite;
pRichEditOle->GetClientSite(&pOleClientSite);
IStorage *pStorage;
LPLOCKBYTES lpLockBytes=NULL;
sc=CreateILockBytesOnHGlobal(NULL,True,&lpLockBytes); //创建全局存储
if(sc!=S_OK)
throw Exception("");
assert(lpLockBytes);
sc=StgCreateDocfileOnILockBytes(lpLockBytes,STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE,
0,&pStorage);
if(sc!=S_OK)
throw Exception("");
assert(pStorage);
IOleObject *pOleObject;
pOleObject=pods->GetOleObject(pOleClientSite,pStorage);
OleSetContainedObject(pOleObject,True);
REOBJECT reobject={0};
reobject.cbStruct=sizeof(reobject);
CLSID clsid;
sc=pOleObject->GetUserClassID(&clsid);
if(sc!=S_OK)
throw Exception("");
reobject.clsid=clsid;
reobject.cp=REO_CP_SELECTION;
reobject.dvaspect=DVASPECT_CONTENT;
reobject.poleobj=pOleObject;
reobject.polesite=pOleClientSite;
reobject.pstg=pStorage;
pRichEditOle->InsertObject(&reobject);
pOleObject->Release();
pOleClientSite->Release();
pStorage->Release();
lpDataObject->Release();
}
void ImageDataObject::SetBitmap(HBITMAP hBitmap)
{
assert(hBitmap);
STGMEDIUM stgm={0};
stgm.tymed=TYMED_GDI;
stgm.hBitmap=hBitmap;
stgm.pUnkForRelease=NULL;
FORMATETC fm;
fm.cfFormat=CF_BITMAP;
fm.ptd=NULL;
fm.dwAspect=DVASPECT_CONTENT;
fm.lindex=-1;
fm.tymed=TYMED_GDI;
this->SetData(&fm,&stgm,True);
}
IOleObject* ImageDataObject::GetOleObject(IOleClientSite *pOleClientSite,IStorage *pStorage)
{
assert(m_stgmed.hBitmap);
SCODE sc;
IOleObject *pOleObject;
sc=OleCreateStaticFromData(this,IID_IOleObject,OLERENDER_FORMAT,
&m_format,pOleClientSite,pStorage,
(void**)&pOleObject);
if(sc!=S_OK)
throw Exception("");
return pOleObject;
}
调用方法:
IRichEditOle* pOle=NULL;
SendMessage(RichEdit1->Handle,EM_GETOLEINTERFACE,0,(LPARAM)&pOle);
assert(pOle);
HBITMAP hBitmap=(HBITMAP)LoadImageA(NULL,"C:/000.BMP",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
assert(hBitmap);
ImageDataObject::InsertBitmap(pOle,hBitmap);
DeleteObject(hBitmap);