首先定义一个类继承自 CRichEditCtrl,头文件定义如下
#pragma once // MyRichEdit class MyRichEdit : public CRichEditCtrl { DECLARE_DYNAMIC(MyRichEdit) public: MyRichEdit(); virtual ~MyRichEdit(); public: void InsertBitmap(CBitmap & bitmap ); protected: DECLARE_MESSAGE_MAP() IRichEditOle *richOle; public: protected: virtual void PreSubclassWindow(); };
然后再cpp文件中实现如下
#include "stdafx.h" #include "MyIPMsg.h" #include "MyRichEdit.h" #include <objidl.h> #include <ole2.h> #include <commctrl.h> #include <richedit.h> #include <oledlg.h> #include <RichOle.h> class TDataObject : IDataObject { private: ULONG refCnt; HBITMAP hBmp; FORMATETC fe; public: TDataObject() { refCnt = 0; memset(&fe, 0, sizeof(fe)); } ~TDataObject() {} STDMETHODIMP QueryInterface(REFIID iid, void **obj); STDMETHODIMP_(ULONG) AddRef(void); STDMETHODIMP_(ULONG) Release(void); STDMETHODIMP GetData(FORMATETC *_fe, STGMEDIUM *sm); STDMETHODIMP SetData(FORMATETC *_fe , STGMEDIUM *sm, BOOL fRelease) { return E_NOTIMPL; } STDMETHODIMP GetDataHere(FORMATETC *_fe, STGMEDIUM *sm) { return E_NOTIMPL; } STDMETHODIMP QueryGetData(FORMATETC *_fe) { return E_NOTIMPL; } STDMETHODIMP GetCanonicalFormatEtc(FORMATETC *_fei ,FORMATETC *_feo) { return E_NOTIMPL; } STDMETHODIMP EnumFormatEtc(DWORD direc, IEnumFORMATETC **ife) { return E_NOTIMPL; } STDMETHODIMP DUnadvise(DWORD conn) { return E_NOTIMPL; } STDMETHODIMP EnumDAdvise(IEnumSTATDATA **nav) { return E_NOTIMPL; } STDMETHODIMP DAdvise(FORMATETC *_fe, DWORD advf, IAdviseSink *as, DWORD *conn) { return E_NOTIMPL; } void InsertBitmap(IRichEditOle *richOle, HBITMAP hBmp); }; HRESULT TDataObject::QueryInterface(REFIID riid, LPVOID* ppv) { *ppv = NULL; if (IID_IUnknown == riid || IID_IDataObject == riid) { *ppv = this; } else return ResultFromScode(E_NOINTERFACE); AddRef(); return S_OK; } HRESULT TDataObject::GetData(FORMATETC *_fe, STGMEDIUM *sm) { HBITMAP hDupBmp = (HBITMAP)::OleDuplicateData(hBmp, CF_BITMAP, NULL); if (!hDupBmp) return E_HANDLE; sm->tymed = TYMED_GDI; sm->hBitmap = hDupBmp; sm->pUnkForRelease = NULL; return S_OK; } ULONG TDataObject::AddRef(void) { refCnt++; return refCnt; } ULONG TDataObject::Release(void) { int ret = --refCnt; if (0 == refCnt) { delete this; } return ret; } void TDataObject::InsertBitmap(IRichEditOle *richOle, HBITMAP _hBmp) { IOleClientSite *ocs = NULL; IStorage *is = NULL; LPLOCKBYTES lb = NULL; IOleObject *oleObj = NULL; REOBJECT reobj; CLSID clsid; hBmp = _hBmp; fe.cfFormat = CF_BITMAP; fe.ptd = NULL; fe.dwAspect = DVASPECT_CONTENT; fe.lindex = -1; fe.tymed = TYMED_GDI; richOle->GetClientSite(&ocs); ::CreateILockBytesOnHGlobal(NULL, TRUE, &lb); if (!ocs || !lb) goto END; ::StgCreateDocfileOnILockBytes(lb, STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &is); if (!is) goto END; ::OleCreateStaticFromData(this, IID_IOleObject, OLERENDER_FORMAT, &fe, ocs, is, (void **)&oleObj); if (!oleObj) goto END; ::OleSetContainedObject(oleObj, TRUE); memset(&reobj, 0, sizeof(REOBJECT)); reobj.cbStruct = sizeof(REOBJECT); oleObj->GetUserClassID(&clsid); reobj.clsid = clsid; reobj.cp = REO_CP_SELECTION; reobj.dvaspect = DVASPECT_CONTENT; reobj.poleobj = oleObj; reobj.polesite = ocs; reobj.pstg = is; richOle->InsertObject(&reobj); END: if (oleObj) oleObj->Release(); if (lb) lb->Release(); if (is) is->Release(); if (ocs) ocs->Release(); } // MyRichEdit IMPLEMENT_DYNAMIC(MyRichEdit, CRichEditCtrl) MyRichEdit::MyRichEdit() { richOle=NULL; } MyRichEdit::~MyRichEdit() { } BEGIN_MESSAGE_MAP(MyRichEdit, CRichEditCtrl) END_MESSAGE_MAP() void MyRichEdit::InsertBitmap( CBitmap & bitmap ) { TDataObject *dataObject=new TDataObject; dataObject->AddRef(); dataObject->InsertBitmap(richOle,(HBITMAP)bitmap.GetSafeHandle());dataObject->Release(); } void MyRichEdit::PreSubclassWindow() { this->SendMessage(EM_GETOLEINTERFACE, 0, (LPARAM)&richOle); CRichEditCtrl::PreSubclassWindow(); }
使用时直接调用void MyRichEdit::InsertBitmap( CBitmap & bitmap )就行,在程序的最初还要进行如下初始化
AfxInitRichEdit();
AfxOleInit();