怎样在CRichEditCtrl中插入BMP图片或GIF文件(类似QQ那样表情符)
http://www.codeguru.com/Cpp/controls/richedit/article.php/c5383/
下载COM底成代码:如下ImageDataObject.hclass CImageDataObject : IDataObject
{
public:
// This static fumction accepts those parameters:
// IRichEditOle* : a pointer to IRochEditOle interface for the RichEdit Control
// HBITMAP : the bitmap handle.
//
// After calling the function, it inserts the image in the current 
//    position of the RichEdit
//
static void InsertBitmap(IRichEditOle* pRichEditOle, HBITMAP hBitmap);private:
ULONG m_ulRefCnt;
BOOL m_bRelease; // The data being bassed to the richedit
//
STGMEDIUM m_stgmed;
FORMATETC m_fromat;public:
CImageDataObject() : m_ulRefCnt(0)
{
m_bRelease = FALSE;
} ~CImageDataObject()
{
if (m_bRelease)
::ReleaseStgMedium(&m_stgmed);
} // Methods of the IUnknown interface
// 
STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject)
{
if (iid == IID_IUnknown || iid == IID_IDataObject)
{
*ppvObject = this;
AddRef();
return S_OK;
}
else
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;
} // Methods of the IDataObject Interface
//
STDMETHOD(GetData)(FORMATETC *pformatetcIn, STGMEDIUM *pmedium) {
HANDLE hDst;
hDst = ::OleDuplicateData(m_stgmed.hBitmap, CF_BITMAP, NULL);
if (hDst == NULL)
{
return E_HANDLE;
} 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*  pformatectIn ,FORMATETC* pformatetcOut )  {
return E_NOTIMPL;
}
STDMETHOD(SetData)(FORMATETC* pformatetc , STGMEDIUM*  pmedium , BOOL  fRelease ) {
m_fromat = *pformatetc;
m_stgmed = *pmedium; return S_OK;
}
STDMETHOD(EnumFormatEtc)(DWORD  dwDirection , IEnumFORMATETC**  ppenumFormatEtc ) {
return E_NOTIMPL;
}
STDMETHOD(DAdvise)(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink,
DWORD *pdwConnection) {
return E_NOTIMPL;
}
STDMETHOD(DUnadvise)(DWORD dwConnection) {
return E_NOTIMPL;
}
STDMETHOD(EnumDAdvise)(IEnumSTATDATA **ppenumAdvise) {
return E_NOTIMPL;
} // Some Other helper functions
//
void SetBitmap(HBITMAP hBitmap);
IOleObject *GetOleObject(IOleClientSite *pOleClientSite, IStorage *pStorage);};
ImageDataObject.cpp#include "stdafx.h"
#include "ImageDataObject.h"#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif//////////////////////////////////////////////////////////////////////
// Static member functions
//////////////////////////////////////////////////////////////////////void CImageDataObject::InsertBitmap(IRichEditOle* pRichEditOle, HBITMAP hBitmap)
{
SCODE sc; // Get the image data object
//
CImageDataObject *pods = new CImageDataObject;
LPDATAOBJECT lpDataObject;
pods->QueryInterface(IID_IDataObject, (void **)&lpDataObject); pods->SetBitmap(hBitmap); // Get the RichEdit container site
//
IOleClientSite *pOleClientSite;
pRichEditOle->GetClientSite(&pOleClientSite); // Initialize a Storage Object
//
IStorage *pStorage; LPLOCKBYTES lpLockBytes = NULL;
sc = ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes);
if (sc != S_OK)
AfxThrowOleException(sc);
ASSERT(lpLockBytes != NULL);

sc = ::StgCreateDocfileOnILockBytes(lpLockBytes,
STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &pStorage);
if (sc != S_OK)
{
VERIFY(lpLockBytes->Release() == 0);
lpLockBytes = NULL;
AfxThrowOleException(sc);
}
ASSERT(pStorage != NULL); // The final ole object which will be inserted in the richedit control
//
IOleObject *pOleObject; 
pOleObject = pods->GetOleObject(pOleClientSite, pStorage); // all items are "contained" -- this makes our reference to this object
//  weak -- which is needed for links to embedding silent update.
OleSetContainedObject(pOleObject, TRUE); // Now Add the object to the RichEdit 
//
REOBJECT reobject;
ZeroMemory(&reobject, sizeof(REOBJECT));
reobject.cbStruct = sizeof(REOBJECT);

CLSID clsid;
sc = pOleObject->GetUserClassID(&clsid);
if (sc != S_OK)
AfxThrowOleException(sc); reobject.clsid = clsid;
reobject.cp = REO_CP_SELECTION;
reobject.dvaspect = DVASPECT_CONTENT;
reobject.poleobj = pOleObject;
reobject.polesite = pOleClientSite;
reobject.pstg = pStorage; // Insert the bitmap at the current location in the richedit control
//
pRichEditOle->InsertObject(&reobject); // Release all unnecessary interfaces
//
pOleObject->Release();
pOleClientSite->Release();
pStorage->Release();
lpDataObject->Release();
}//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////void CImageDataObject::SetBitmap(HBITMAP hBitmap)
{
ASSERT(hBitmap); STGMEDIUM stgm;
stgm.tymed = TYMED_GDI; // Storage medium = HBITMAP handle
stgm.hBitmap = hBitmap;
stgm.pUnkForRelease = NULL; // Use ReleaseStgMedium FORMATETC fm;
fm.cfFormat = CF_BITMAP; // Clipboard format = CF_BITMAP
fm.ptd = NULL; // Target Device = Screen
fm.dwAspect = DVASPECT_CONTENT; // Level of detail = Full content
fm.lindex = -1; // Index = Not applicaple
fm.tymed = TYMED_GDI; // Storage medium = HBITMAP handle this->SetData(&fm, &stgm, TRUE);
}IOleObject *CImageDataObject::GetOleObject(IOleClientSite *pOleClientSite, IStorage *pStorage)
{
ASSERT(m_stgmed.hBitmap); SCODE sc;
IOleObject *pOleObject;
sc = ::OleCreateStaticFromData(this, IID_IOleObject, OLERENDER_FORMAT, 
&m_fromat, pOleClientSite, pStorage, (void **)&pOleObject);
if (sc != S_OK)
AfxThrowOleException(sc);
return pOleObject;
}在InsertBitmap()函数中怎样修改才能像QQ哪样动态的表情图才能实现,大家帮帮忙,本人急用,请高手多支持。