资源大全 | 神秘文化 | 在线翻译 | QQ专区 | 视频教程 | 彩信频道 | 搜索引擎 | BT下载 |  | 网站地图
设为首页
加入收藏
联系站长
您现在的位置: 一百网络 >> 其他编程 >> C++编程 >> 文档正文
最近更新
普通文档 mutable的用法
普通文档 stringstream的用法
普通文档 explicit的用法
普通文档 VHDL语言数字钟
普通文档 自定义Firefox的配置保存
普通文档 subversion服务器的配置
普通文档 一段代码的几种写法-怎么
普通文档 如何判断一个COM对象是否
普通文档 纯技术讨论com控件创建过
普通文档 string 类的使用方法
推荐文章
推荐文档 专家教您如何在C语言中巧
推荐文档 详细解析C++编写的ATM自
推荐文档 C++编程中的四个调试小技
推荐文档 Windows下C语言网络编程
推荐文档 Visual C++常用数据类型
推荐文档 COM组件设计与应用之实现
推荐文档 利用VC实现图像的特殊显
纯技术讨论com控件创建过程

文章作者:未知 录入时间:2007-7-10 来源:本站原创
网站声明:本站的文章除部分特别声明禁止转载的专稿外,可以自由转载.但请务必注明出处和原始作者,文章版权归本网站与文章作者所有。对于被本站转载文章的个人和网站,我们表示深深的谢意。

用一个没有任何意义的例子来看看com控件的创建过程。又是狠狠忙了一阵子。前几天,一个网上的朋友找到我,他想在richedit里面插入一个ax控件,这个倒是很简单,网上也很多。接下来,他想要在richedit里面插入一个窗口,当然无论ax控件是否设置m_bWindowOnly都无法达到需求。我给他的答案是不行,其实我不知道该如何解释这个问题。不管需求如何怪异,也不管是否解决了他的问题,这里我单纯来强行插入一个窗口到richedit,不关心插入进去是否可以正常工作。声明,这是一个没有意义的事情,只是想说明com控件创建过程。

一个支持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,
创建com控件。

我们有时候看见这样的创建方式: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();
}
我要创建自己的ControlSite,而CreateControlSite是protect的,所以我的派生一下:
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 
= 2020 };
    SIZE sz 
= 300300 };
    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();
这样就ok拉。上面反映了一个控件入住一个窗体的过程。

效果:



 
  • 上一篇文档:

  • 下一篇文档:
  •     查找更多“[组图]纯技术讨论com控件创建过程”的内容  
    相关连接
  • mutable的用法

  • stringstream的用法

  • explicit的用法

  • VHDL语言数字钟

  • 自定义Firefox的配置保存路径