|
|
|
|
一个支持com控件的窗口必须创建CWnd的COleControlContainer* m_pCtrlCont; // for containing OLE controls,通过BOOL InitControlContainer();函数,它又会调用虚函数virtual BOOL CreateControlContainer(COleControlContainer** ppContainer);你可以重载来创建你自己的Container。而这个冬冬就好比一个宾馆,每个控件好比一个人,有人生自由,可以入住任何一个宾馆,但是一旦寄宿在一家宾馆,这个宾馆必须为之提供一个房间,这是ControlSite的概念,创建调用: virtual BOOL CreateControlSite(COleControlContainer* pContainer, COleControlSite** ppSite, UINT nID, REFCLSID clsid);再通过: virtual HRESULT CreateControl(CWnd* pWndCtrl, REFCLSID clsid, LPCTSTR lpszWindowName, DWORD dwStyle, const POINT* ppt, const SIZE* psize, UINT nID, CFile* pPersist=NULL, BOOL bStorage=FALSE,我们有时候看见这样的创建方式:CWnd::CreateControl()来创建com控件。这其中经历了父窗口初始化ControlContainer,准备一个ControlSite,把com控件创建并安排到此房间并做一些初始化操作,然后把com控件窗口句柄(如果存在)依附到CWnd,这里CWnd充当的是一个与控件通信的代理。可以看出是否创建有窗口还是无窗口的,依赖CreateControl内部操作。再控件里面,我们看到控件实现了这样两个接口: COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless) COM_INTERFACE_ENTRY(IOleInPlaceObject) 他们接口大同小异,一个是有窗口方式一个是无窗口方式,为什么这么做是历史原因,因为窗口耗费大量资源。在不深究下去,有兴趣可以找点老古典来瞅瞅。 下面开始我的创建过程: 我想实现在RichEdit里面创建一个房间(ControlSite)来容纳一个web控件,由于COleControlSite不让我new出来,所以我的继承一个CMyOleControlSite: class CMyOleControlSite : public COleControlSite![]() ![]() { public:![]() CMyOleControlSite(COleControlContainer* pCtrlCont) : COleControlSite(pCtrlCont) {}![]() protected: // Implementation LPUNKNOWN GetInterfaceHook(const void *iid); // IUnknown methods STDMETHOD(QueryInterface)(REFIID riid, void **ppvObject); STDMETHOD_(ULONG, AddRef)(); STDMETHOD_(ULONG, Release)(); };![]() LPUNKNOWN CMyOleControlSite::GetInterfaceHook(const void *iid)![]() ![]() { if (IsEqualIID((REFIID) (*(IID*)iid), IID_IDocHostUIHandler)) return (IDocHostUIHandler *) this; return NULL; }![]() // IUnknown methods STDMETHODIMP CMyOleControlSite::QueryInterface(REFIID riid, void **ppvObject)![]() ![]() { return COleControlSite::ExternalQueryInterface(&riid, ppvObject); } STDMETHODIMP_(ULONG) CMyOleControlSite::AddRef()![]() ![]() { return ExternalAddRef(); }![]() STDMETHODIMP_(ULONG) CMyOleControlSite::Release()![]() ![]() { return ExternalRelease(); } class CMyRichEditCtrl : public CRichEditCtrl![]() ![]() { friend class CTestCtrlInRichEditDlg; DECLARE_DYNAMIC(CMyRichEditCtrl) public: CWnd m_wndCtrl;![]() BOOL CreateControlSite(COleControlContainer* pContainer, ![]() COleControlSite** ppSite, UINT /**//* nID */, REFCLSID /**//* clsid */); }; IMPLEMENT_DYNAMIC(CMyRichEditCtrl, CRichEditCtrl)![]() BOOL CMyRichEditCtrl::CreateControlSite(COleControlContainer* pContainer, ![]() COleControlSite** ppSite, UINT /**//* nID */, REFCLSID /**//* clsid */)![]() ![]() { if(ppSite == NULL)![]() { ASSERT(FALSE); return FALSE; }![]() CMyOleControlSite *pOleSite = new CMyOleControlSite(pContainer);![]() *ppSite = pOleSite; (*ppSite)->m_pCtrlCont = pContainer; return TRUE; }在对话框的OnInitDialog函数里面: m_wndRichCtrl.InitControlContainer();![]() COleControlSite* pControlSite = NULL;![]() m_wndRichCtrl.CreateControlSite(m_wndRichCtrl.GetControlContainer(), &pControlSite, 102, CLSID_NULL/**//*CLSID_WebBrowser*/);![]() POINT pt = { 20, 20 };![]() SIZE sz = { 300, 300 }; pControlSite->CreateControl(&m_wndRichCtrl.m_wndCtrl, CLSID_WebBrowser, _T("^_^"), WS_VISIBLE|WS_CHILD|WS_TABSTOP|WS_GROUP, &pt, &sz, 102); COleControlSiteOrWnd* pSiteOrWnd = new COleControlSiteOrWnd(pControlSite); m_wndRichCtrl.GetControlContainer()->m_listSitesOrWnds.AddTail(pSiteOrWnd); IWebBrowser2* pIWebBrowser = NULL; pControlSite->m_pInPlaceObject->QueryInterface(IID_IWebBrowser2, (void**)&pIWebBrowser); pIWebBrowser->Navigate2(&CComVariant("www.cppblog.com/wlwlxj"), NULL, NULL, NULL, NULL); pIWebBrowser->Release(); IOleControl* pIOleCtrl = NULL; pControlSite->m_pInPlaceObject->QueryInterface(IID_IOleControl, (void**)&pIOleCtrl); pIOleCtrl->Release();效果: |








CMyOleControlSite(COleControlContainer
}
}