richedit插入gif实例下载:
OLE封装库
RICHEDIT_DEMO
1、创建ATL复合文档控件。可通过wizard创建。
下面是创建OLE控件的最小头文件
// CSimpleOleObject
class ATL_NO_VTABLE CSimpleOleObject :
public CComObjectRootEx,
public IDispatchImpl,
public IPersistStreamInitImpl,
public IOleControlImpl,
public IOleObjectImpl,
public IOleInPlaceActiveObjectImpl,
public IViewObjectExImpl,
public IOleInPlaceObjectWindowlessImpl,
#ifdef _WIN32_WCE // 要在 Windows CE 上正确加载该控件,要求 IObjectSafety
public IObjectSafetyImpl,
#endif
public CComCoClass,
public CComCompositeControl
{
public:
CSimpleOleObject()
{
m_bWindowOnly = TRUE;
CalcExtent(m_sizeExtent);
}
DECLARE_OLEMISC_STATUS(OLEMISC_RECOMPOSEONRESIZE |
OLEMISC_CANTLINKINSIDE |
OLEMISC_INSIDEOUT |
OLEMISC_ACTIVATEWHENVISIBLE |
OLEMISC_SETCLIENTSITEFIRST
)
DECLARE_REGISTRY_RESOURCEID(IDR_SIMPLEOLEOBJECT)
BEGIN_COM_MAP(CSimpleOleObject)
COM_INTERFACE_ENTRY(ISimpleOleObject)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IViewObjectEx)
COM_INTERFACE_ENTRY(IViewObject2)
COM_INTERFACE_ENTRY(IViewObject)
COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless)
COM_INTERFACE_ENTRY(IOleInPlaceObject)
COM_INTERFACE_ENTRY2(IOleWindow, IOleInPlaceObjectWindowless)
COM_INTERFACE_ENTRY(IOleInPlaceActiveObject)
COM_INTERFACE_ENTRY(IOleControl)
COM_INTERFACE_ENTRY(IOleObject)
COM_INTERFACE_ENTRY(IPersistStreamInit)
COM_INTERFACE_ENTRY2(IPersist, IPersistStreamInit)
#ifdef _WIN32_WCE // 要在 Windows CE 上正确加载该控件,要求 IObjectSafety
COM_INTERFACE_ENTRY_IID(IID_IObjectSafety, IObjectSafety)
#endif
END_COM_MAP()
BEGIN_PROP_MAP(CSimpleOleObject)
PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4)
PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
// 示例项
// PROP_ENTRY_TYPE("属性名", dispid, clsid, vtType)
// PROP_PAGE(CLSID_StockColorPage)
END_PROP_MAP()
BEGIN_MSG_MAP(CSimpleOleObject)
CHAIN_MSG_MAP(CComCompositeControl)
END_MSG_MAP()
// 处理程序原型:
// LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
// LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
// LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);
BEGIN_SINK_MAP(CSimpleOleObject)
//请确保事件处理程序含有 __stdcall 调用约定
END_SINK_MAP()
STDMETHOD(OnAmbientPropertyChange)(DISPID dispid)
{
if (dispid == DISPID_AMBIENT_BACKCOLOR)
{
SetBackgroundColorFromAmbient();
FireViewChange();
}
return IOleControlImpl::OnAmbientPropertyChange(dispid);
}
// IViewObjectEx
DECLARE_VIEW_STATUS(VIEWSTATUS_SOLIDBKGND | VIEWSTATUS_OPAQUE)
// ISimpleOleObject
enum { IDD = IDD_SIMPLEOLEOBJECT };
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
};
OBJECT_ENTRY_AUTO(__uuidof(SimpleOleObject), CSimpleOleObject)
2、设置你需要的属性,这些数据是需要存储的,需要在复制和粘贴时使用:
BEGIN_PROP_MAP(CContactOleObject)
PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4)
PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
PROP_ENTRY_TYPE("Caption", DISPID_CAPTION, CLSID_NULL, VT_BSTR)
// 示例项
// PROP_ENTRY_TYPE("属性名", dispid, clsid, vtType)
// PROP_PAGE(CLSID_StockColorPage)
END_PROP_MAP()
3、实现IRichEditOleCallBack接口,并在创建RichEdit实例时设置该接口
class ATL_NO_VTABLE CRichEditOleCallback :
public CComObjectRootEx,
public CComCoClass,
public IRichEditOleCallback
{
public:
CRichEditOleCallback();
DECLARE_NO_REGISTRY()
BEGIN_COM_MAP(CRichEditOleCallback)
COM_INTERFACE_ENTRY_IID(IID_IRichEditOleCallback, IRichEditOleCallback)
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
public:
STDMETHOD(Init)(HWND hRich);
STDMETHOD(UnInit)();
// IRichEditOleCallback
STDMETHOD(GetNewStorage)(LPSTORAGE* lplpstg);
STDMETHOD(GetInPlaceContext)(LPOLEINPLACEFRAME FAR *lplpFrame,
LPOLEINPLACEUIWINDOW FAR *lplpDoc, LPOLEINPLACEFRAMEINFO lpFrameInfo);
STDMETHOD(ShowContainerUI)(BOOL fShow);
STDMETHOD(QueryInsertObject)(LPCLSID lpclsid, LPSTORAGE lpstg, LONG cp);
STDMETHOD(DeleteObject)(LPOLEOBJECT lpoleobj);
STDMETHOD(QueryAcceptData)(LPDATAOBJECT lpdataobj, CLIPFORMAT FAR *lpcfFormat,
DWORD reco, BOOL fReally, HGLOBAL hMetaPict);
STDMETHOD(ContextSensitiveHelp)(BOOL fEnterMode);
STDMETHOD(GetClipboardData)(CHARRANGE FAR *lpchrg, DWORD reco, LPDATAOBJECT FAR *lplpdataobj);
STDMETHOD(GetDragDropEffect)(BOOL fDrag, DWORD grfKeyState, LPDWORD pdwEffect);
STDMETHOD(GetContextMenu)(WORD seltyp, LPOLEOBJECT lpoleobj, CHARRANGE FAR *lpchrg, HMENU FAR *lphmenu);
private:
HWND m_hRich;
int m_iNumStorages;
IStoragePtr m_spStorage;
};
4、OLE中增加插入到richedit的接口:
virtual HRESULT STDMETHODCALLTYPE InsertOleObjectToRichEdit(IUnknown* pRichEditOle)
{
if(pRichEditOle == NULL)
return E_FAIL;
T* pT = static_cast(this);
if(pT->m_spClientSite)
{
// 如果当前已经嵌入了某个容器中,就不能再插了
return S_FALSE;
}
IOleObjectPtr spOleObject = NULL; //OLE对象
IOleClientSitePtr spClientSite = NULL;
CComPtr spRichEditOle = NULL;
CLSID clsid = CLSID_NULL;
HRESULT hr = S_OK;
BOOL bRet = TRUE;
hr = pRichEditOle->QueryInterface(IID_IRichEditOle, (void**)&spRichEditOle);
hr = spRichEditOle->GetClientSite(&spClientSite);
hr = pT->QueryInterface(IID_IOleObject, (void**)&spOleObject);//获得数据对象接口
GetUserClassID(&clsid);
REOBJECT reobject;
ZeroMemory(&reobject, sizeof(REOBJECT)); //初始化一个对象
reobject.cbStruct = sizeof(REOBJECT);
reobject.clsid = clsid;
reobject.cp = REO_CP_SELECTION;
reobject.dvaspect = DVASPECT_CONTENT;
reobject.dwFlags = REO_DONTNEEDPALETTE | REO_DYNAMICSIZE;
reobject.poleobj = spOleObject;
reobject.polesite = spClientSite;
reobject.pstg = m_spStorage;
spOleObject->SetClientSite(spClientSite);
hr = spRichEditOle->InsertObject( &reobject );
::OleSetContainedObject(spOleObject,TRUE);
return S_OK;
}
5、使用一下代码插入OLE
CComQIPtr spCusOle;
HRESULT hr = CoCreateInstance(__uuidof(SimpleOleObject), NULL, CLSCTX_INPROC, __uuidof(ISimpleOleObject), (void**)&spCusOle);
if(spCusOle)
{
spCusOle->SetImageFile(_bstr_t(sFile));
IOleObjectPtr spOleObject;
spCusOle->QueryInterface(IID_IOleObject, (void**)&spOleObject);
CComPtr spEditOle;
spEditOle.Attach(GetIRichEditOle());
IOleClientSitePtr spClientSite;
spEditOle->GetClientSite(&spClientSite);
spCusOle->InsertOleObjectToRichEdit(spEditOle);
}