深入探索COM开发框架 之 MFC和ATL [四]

原创 2003年04月03日 08:54:00

static const AFX_DISPMAP* PASCAL _GetBaseDispatchMap(); /<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

       virtual const AFX_DISPMAP* GetDispatchMap() const; /

 

#else

#define DECLARE_DISPATCH_MAP() /

private: /

       static const AFX_DISPMAP_ENTRY _dispatchEntries[]; /

       static UINT _dispatchEntryCount; /

       static DWORD _dwStockPropMask; /

protected: /

       static AFX_DATA const AFX_DISPMAP dispatchMap; /

       virtual const AFX_DISPMAP* GetDispatchMap() const; /

#endif

------------------------------------------------------

#ifdef _AFXDLL

#define BEGIN_DISPATCH_MAP(theClass, baseClass) /

       const AFX_DISPMAP* PASCAL theClass::_GetBaseDispatchMap() /

                { return &baseClass::dispatchMap; } /

       const AFX_DISPMAP* theClass::GetDispatchMap() const /

                { return &theClass::dispatchMap; } /

       AFX_COMDAT const AFX_DISPMAP theClass::dispatchMap = /

                { &theClass::_GetBaseDispatchMap, &theClass::_dispatchEntries[0], /

                         &theClass::_dispatchEntryCount, &theClass::_dwStockPropMask }; /

       AFX_COMDAT UINT theClass::_dispatchEntryCount = (UINT)-1; /

       AFX_COMDAT DWORD theClass::_dwStockPropMask = (DWORD)-1; /

       AFX_COMDAT const AFX_DISPMAP_ENTRY theClass::_dispatchEntries[] = /

       { /

#else

#define BEGIN_DISPATCH_MAP(theClass, baseClass) /

       const AFX_DISPMAP* theClass::GetDispatchMap() const /

                { return &theClass::dispatchMap; } /

       AFX_COMDAT const AFX_DISPMAP theClass::dispatchMap = /

                { &baseClass::dispatchMap, &theClass::_dispatchEntries[0], /

                         &theClass::_dispatchEntryCount, &theClass::_dwStockPropMask }; /

       AFX_COMDAT UINT theClass::_dispatchEntryCount = (UINT)-1; /

       AFX_COMDAT DWORD theClass::_dwStockPropMask = (DWORD)-1; /

       AFX_COMDAT const AFX_DISPMAP_ENTRY theClass::_dispatchEntries[] = /

{ /

#endif

#define END_DISPATCH_MAP() /

       { VTS_NONE, DISPID_UNKNOWN, VTS_NONE, VT_VOID, /

                (AFX_PMSG)NULL, (AFX_PMSG)NULL, (size_t)-1, afxDispCustom } }; /

 

思路跟上面的接口映射表的如出一辙.这里不详细叙述.

关于Automation问题,我想过两天,专门写一篇文章谈谈.

因为Automation的确是一门范围很广的技术,不能说有多么的

,不过细节很多,而且普遍的论述概念不清.

在上面几个宏中出现的结构倒需要提一下:

struct AFX_DISPMAP_ENTRY

{

       LPCTSTR lpszName;       // 分发的方法或属性名                        

       long lDispID;           // 接口分发ID (may be DISPID_UNKNOWN)

       LPCSTR lpszParams;      // 传递的参数

       WORD vt;                // 返回值类型或属性类型

       AFX_PMSG pfn;           // normal member On<membercall> or, OnGet<property>

       AFX_PMSG pfnSet;        // special member for OnSet<property>

       size_t nPropOffset;     // 偏移量,这个地方是核心

       AFX_DISPMAP_FLAGS flags;// flags (e.g. stock/custom)

};

struct AFX_DISPMAP

{

#ifdef _AFXDLL

       const AFX_DISPMAP* (PASCAL* pfnGetBaseMap)();

#else

       const AFX_DISPMAP* pBaseMap;

#endif

       const AFX_DISPMAP_ENTRY* lpEntries;

       UINT* lpEntryCount;

       DWORD* lpStockPropMask;  //是否用备用的名称

};

 

总之,即使在组件类寻到接口时,会按分发的方式来执行方法或更改属性,不会直接执行.

 

 

PART5-------组件得以使用的纽带:几个核心函数

 

  自然,组件的使用不是一呼既来的,从调用接口查询函数开始,

程序内部就开始了漫漫的寻找和创建过程 :

no1.

COleObjectFactory::RegisterAll();

在应用初始化时,调用.目的何在 ? 无非是注册类厂.

(这个地方,本人认为是加载了所有的类厂对象.

因为下面可以直接使用类厂指针链中的类厂指针了)

no2.

AFX_MANAGE_STATE(AfxGetStaticModuleState());

MFC开发的以CwinApp对象为核心的

组件中, AFX_MANAGE_STATE(AfxGetStaticModuleState());

必须在具体操作前调用,因为它掌握着程序所有的信息.

而在ATL,CcomModel对象,内部进行了协调.

一切行为由CcomModel对象来调度.

 

No3.

AfxDllGetClassObject(rclsid, riid, ppv);

你想得到希望的接口指针,获得类厂指针这一步是必须的.

而获得类厂指针是AfxDllGetClassObject(rclsid, riid, ppv);

完成的,它在使用前必须调用

AFX_MANAGE_STATE(AfxGetStaticModuleState());

来监视程序状态,

代码如下:

SCODE AFXAPI AfxDllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)

{

        *ppv = NULL;

        DWORD lData1 = rclsid.Data1;

 

        // search factories defined in the application

        AFX_MODULE_STATE* pModuleState = AfxGetModuleState();

        AfxLockGlobals(CRIT_OBJECTFACTORYLIST);

        for (COleObjectFactory* pFactory = pModuleState->m_factoryList;

          pFactory != NULL; pFactory = pFactory->m_pNextFactory)

        {

                 if (pFactory->m_bRegistered != 0 &&

                   lData1 == pFactory->m_clsid.Data1 &&

                   ((DWORD*)&rclsid)[1] == ((DWORD*)&pFactory->m_clsid)[1] &&

                   ((DWORD*)&rclsid)[2] == ((DWORD*)&pFactory->m_clsid)[2] &&

                   ((DWORD*)&rclsid)[3] == ((DWORD*)&pFactory->m_clsid)[3])

                 {

                   // found suitable class factory -- query for correct interface

                   SCODE sc = pFactory->InternalQueryInterface(&riid, ppv);

                   AfxUnlockGlobals(CRIT_OBJECTFACTORYLIST);

                   return sc;

                 }

        }

        AfxUnlockGlobals(CRIT_OBJECTFACTORYLIST);

#ifdef _AFXDLL

        AfxLockGlobals(CRIT_DYNLINKLIST);

        // search factories defined in extension DLLs

        for (CDynLinkLibrary* pDLL = pModuleState->m_libraryList; pDLL != NULL;

          pDLL = pDLL->m_pNextDLL)

        {

          for (pFactory = pDLL->m_factoryList;

                   pFactory != NULL; pFactory = pFactory->m_pNextFactory)

                 {

                   if (pFactory->m_bRegistered != 0 &&

                             lData1 == pFactory->m_clsid.Data1 &&

                     ((DWORD*)&rclsid)[1] == ((DWORD*)&pFactory->m_clsid)[1] &&

                     ((DWORD*)&rclsid)[2] == ((DWORD*)&pFactory->m_clsid)[2] &&

                     ((DWORD*)&rclsid)[3] == ((DWORD*)&pFactory->m_clsid)[3])

                   {

                             // found suitable class factory -- query for correct interface

                             SCODE sc = pFactory->InternalQueryInterface(&riid, ppv);

                     AfxUnlockGlobals(CRIT_DYNLINKLIST);

                             return sc;

                   }

                 }

        }

        AfxUnlockGlobals(CRIT_DYNLINKLIST);

#endif

 

        // factory not registered -- return error

        return CLASS_E_CLASSNOTAVAILABLE;

}

 

代码简要说明:

在通过CLSIDIID调用组件导出函数DllGetClassObject,首先

会监测程序环境,然后调用AfxDllGetClassObject,AfxDllGetClassObject

内部的操作是这样的,它会从程序维护的全局信息中(

还有进线程信息、资源句柄等)的注册的类厂表中,根据CLSID搜索

相应的类厂,则从本dll引用的扩展dll中搜索.

 

OK !基本上,MFC对于COM的基础支持,就是通过上面这些宏

来实现的

 

------------------------------------------------------------------------------------

待续                      ATL

------------------------------------------------------------------------------------

                          郑重声明:

                 允许复制、修改、传递或其它行为

                 但不准用于任何商业用途.

                      写于  1/4/2003

                      最后修改: 1/4/2003

                         By RedStar81

                      81_RedStar@163.com

------------------------------------------------------------------------------------

 

我的COM和ATL的学习

首先声明本人并非COM/ATL高手,尽管本人接触他们已经有4年了,但是因为工作中的一些原因一直未能深入研究和广泛的实际的使用它们。不过回想学习它们的痛苦经历,实在是有点不堪回首。在此仅以此文和大家探讨...
  • chenlycly
  • chenlycly
  • 2014年10月12日 17:33
  • 891

COM组件开发(六)——使用ATL开发COM组件

使用ATL开发COM组件           使用ATL开发COM组件之前,要对几个重要的类进行说明:           CComModule           这是ATL的中心模块类,它的...
  • q5806622
  • q5806622
  • 2015年02月27日 10:10
  • 2230

ATL和MFC创建ActiveX控件的区别

ATL和MFC创建ActiveX控件的区别 ATL和MFC创建ActiveX控件的区别 在visual C++ 6.0中,ATL和MFC代表了两种不同的框架,分别面向不同类型的基于Window...
  • ljh081231
  • ljh081231
  • 2014年04月11日 10:18
  • 4602

VS2010 简单ATL COM开发(下)

前面一章介绍了怎么创建ATL COM组件及注册,下面简单介绍如何调用COM组件。 1、在MFC中调用有一种很方便的方法,就是通过ClassWizard利用类型库生成包装类,不过有个前提就是com...
  • wangwenjing90
  • wangwenjing90
  • 2013年04月08日 15:11
  • 12972

VS2010 简单ATL COM开发(上)

1、打开VS2010,新建ATL COM 项目,步骤:“文件” --》“新建” --》“项目”,选择“Visual C++” --》“ATL 项目” ,填写“名称” FirstCOM --》“确定”。...
  • wangwenjing90
  • wangwenjing90
  • 2013年04月08日 14:03
  • 17734

创建ATL工程及使用MFC测试COM组件

一、创建ATL工程 1、创建ATL项目,取名为MyATL 2、在ATL项目向导中,勾选【支持MFC】(利用MFC测试用)、【支持 COM+ 1.0】和【支持部件注册器】,其余的选项默认,点击完...
  • jiangqin115
  • jiangqin115
  • 2015年09月06日 17:47
  • 797

[COM/ATL]组件、对象、MFC、ATL的区别

组件(Component)和对象(Object)之间的区别 先明确组件(Component)和对象(Object)之间的区别。组件是一个可重用的模块,它是由一 组处理过程、数据封装和用户接口组成的业...
  • ouyangshima
  • ouyangshima
  • 2013年07月19日 19:58
  • 1539

OLE、ActiveX、COM、ATL联系与区别

熟悉面向对象编程和网络编程的人一定对ActiveX、OLE和COM/DCOM这些概念不会陌生,但是它们之间究竟是什么样的关系,对许多们还是比较模糊的。在具体介绍它们的关系之间,我们还是先明确组件(Co...
  • lp310018931
  • lp310018931
  • 2015年09月19日 18:09
  • 1026

COM组件(ATL篇)

目 录 第1章 创建进程内组件    1 1.1 目标    1 1.2 创建项目    3 1.2.1 VC++6.0    3 1.2....
  • Hanford
  • Hanford
  • 2016年11月25日 21:45
  • 1082

C++ STL,ATL,WTL之间的联系和区别

STL即 Standard Template Library (标准模板库) STL是惠普实验室开发的一系列软件的统称。它是由Alexander Stepanov、Meng Lee和Davi...
  • xdrt81y
  • xdrt81y
  • 2013年12月05日 16:09
  • 11293
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深入探索COM开发框架 之 MFC和ATL [四]
举报原因:
原因补充:

(最多只允许输入30个字)