RichEdit嵌入自开发OLE控件技术要点(ATL)

RichEdit嵌入自开发OLE控件技术要点(ATL)

richedit插入gif实例下载:

OLE封装库

RICHEDIT_DEMO

1、创建ATL复合文档控件。可通过wizard创建。
下面是创建OLE控件的最小头文件

// CSimpleOleObject
class ATL_NO_VTABLE CSimpleOleObject :
	public CComObjectRootEx<CComSingleThreadModel>,
	public IDispatchImpl<ISimpleOleObject, &IID_ISimpleOleObject, &LIBID_atlsdLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
	public IPersistStreamInitImpl<CSimpleOleObject>,
	public IOleControlImpl<CSimpleOleObject>,
	public IOleObjectImpl<CSimpleOleObject>,
	public IOleInPlaceActiveObjectImpl<CSimpleOleObject>,
	public IViewObjectExImpl<CSimpleOleObject>,
	public IOleInPlaceObjectWindowlessImpl<CSimpleOleObject>,
#ifdef _WIN32_WCE // 要在 Windows CE 上正确加载该控件,要求 IObjectSafety
	public IObjectSafetyImpl<CSimpleOleObject, INTERFACESAFE_FOR_UNTRUSTED_CALLER>,
#endif
	public CComCoClass<CSimpleOleObject, &CLSID_SimpleOleObject>,
	public CComCompositeControl<CSimpleOleObject>
{
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<CSimpleOleObject>)
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<CSimpleOleObject>::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<CComSingleThreadModel>,
	public CComCoClass<CRichEditOleCallback, &CLSID_NULL>,
	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<T*>(this);

        if(pT->m_spClientSite)
        {
            // 如果当前已经嵌入了某个容器中,就不能再插了
            return S_FALSE;
        }

        IOleObjectPtr  spOleObject              = NULL; //OLE对象
        IOleClientSitePtr spClientSite          = NULL;
        CComPtr<IRichEditOle> 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<ISimpleOleObject> 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<IRichEditOle> spEditOle;
        spEditOle.Attach(GetIRichEditOle());
        IOleClientSitePtr spClientSite;
        spEditOle->GetClientSite(&spClientSite);

        spCusOle->InsertOleObjectToRichEdit(spEditOle);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值