首先定義一個類繼承自 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();