【php精品源码栏目提醒】:以下是网学会员为您推荐的php精品源码-MFC与ATL - 培训教程,希望本篇文章对您学习有所帮助。
处理 SSI 文件时出错 show_otherlinks 这就是我 详细信息 站内订阅0 加为好友 发送短信 日志:20 评论:8 留言:2 访问: 最新公告 大家好欢迎光临醉晚亭的blog该blog主要以学习为主如果你有什么问题请留言谢谢 站点日历 ltlt lt 2006 - 5 gt gtgt 日 一 二 三 四 五 六 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 最新日志 谈谈我的求职经历 ·制作控件ATL和MFC应该使用哪个 -zuiwanting 发表于 2006-5-24 9:59:00 摘要目前MFC和ATL代表了两种框架分别面向不同类型的基于Windows的开发。
MFC代表了创建独立的Windows应用的一种简单、一致的方法ATL提供了一种框架来实现创建COM客户机和服务器所必须的样板文件代码。
这两种框架在它们对于开发ActiveX的用途上会合了。
我们将看看这两种框架是如何适用于创建ActiveX控件的——突出其优缺点亲自经历创建一个控件的过程——以便你能够决定何时使用一种框架何时使用另一种。
-------------------------------------------------------------------------------- 如果你希望用C来写ActiveXampreg控件有两个流行的框架一个是Microsoftampreg Foundation Classes MFC另一个是ATL。
我将深入的解释这两种框架对开发ActiveX控件所提供的支持帮助你更好的决定哪种模型最适合你的开发环境和需求。
ActiveX控件的完全形态 ActiveX控件基于构件对象模型COM使得ActiveX控件成为可能的COM的基本原则是一个对象的接口和其实现能够而且应该分开对待。
只要COM的对象和它的客户方代码就接口细节达成了一致如何实现就不成其问题。
ActiveX控件展示了大量ActiveX控件包容器理解的接口。
因为客户方代码和控件认可这些接口的外在表现你可以编写一个ActiveX控件然后简单的将它放入包容器中。
包容器将通过良好定义的接口来驱动控件而这些控件将以自己的方式做出合适的响应。
在更高的层次上一个ActiveX控件是实现了几个主要ActiveX技术的一个COM对象包括通常的引入COM接口OLE嵌入协议连接点和属性页。
在较低的编程层次上ActiveX控件只是实现了某些类型接口的COM类。
当一些客户方代码成功的查询到这些接口之一时它就知道如何使用一个ActiveX控件了。
一个ActiveX控件暴露的接口主要分为3类。
第一ActiveX控件是可嵌入的对象就是说它们实现了大多数的OLE文档、in-place激活和嵌入协议。
ActiveX控件实现了如下的接口 IOleObject IPersistStorage IDataObject IOleInPlaceActiveObject IOleInPlaceObject IViewObject2和IRunnableObject 这一个很少用到. 第二ActiveX控件通常都支持属性页这样客户方就可以修改控件的属性了。
最后ActiveX控件通常都利用COM的连接点技术实现了客户方能发现的外出接 openvpn
源码分析 pragma指令用法zz OpenVPN-HOWTO中文版Z 华为笔试题 apache
php 安装 2005百度之星竞赛题程序 制作控件ATL和MFC应该使用哪 关于证书和签名 制作CAB 最新回复 Re:pragma指令用法zz Re:2005百度之星竞赛题程序 Re:2005百度之星竞赛题程序 Re:2005百度之星竞赛题程序 Re:华为笔试题 ampnb Re:无光驱无软驱安装操作系统 Re:VS2005的一个问题没有找 Re:VS2005的一个问题没有找 Re:我和宝贝儿 Re:VS2005的一个问题没有找 最新留言 ::签写留言:: 端午节加儿童节快乐啦 晃晃悠悠 日志搜索 口。
为了帮助比较ATL和MFC框架我们来看一下写在每一种框架中的相同的控件。
此控件监视创建它的线程上传递的消息流。
消息流控件是一个很不错的例子因为它演示了一个ActiveX控件所有主要的方面包括送入接口、外出接口属性永久性以及属性页。
让我们从研究这两个框架提供的标准的COM支持开始吧。
MFC的基本COM支持 Microsoft建立MFC使得开发Windowsampreg应用程序比使用SDK容易多了。
有了MFCMicrosoft接着增加了对即存框架的COM支持。
这意味着MFC的开发者在增加越来越多的函数时必须保持框架的完整。
同时Visual Campreg编译器那时还不支持模板因此它们不得不借助非模板的其它手段来将COM功能掺入它们的类中。
Microsoft通过加入一些虚函数到CcmdTarget类和一些宏中解决了这个问题使得在MFC中实现COM接口有了可能。
MFC内部的COM支持从CcmdTarget开始CcmdTarget类实现了Iunknown接口还包括了一个用于引用计数的成员变量m_dwRef以及用于实现IUnknown 的6个函数: InternalAddRef InternalRelease InternalQueryInterface ExternalAddRef ExternalRelease 和 ExternalQueryInterface.。
QueryInterface的两个版本——AddRef和Release支持COM聚合。
InternalAddRef InternalRelease和InternalQueryInterface完成引用计数和QueryInterface操作而ExternalAddRef ExternalRelease和 ExternalQueryInterface代理控制聚合的对象如果此对象参与聚合的话。
MFC使用嵌套的类复合策略来实现COM接口。
在MFC中想实现COM 接口的类是从CcmdTarget中派生的。
每个由CcmdTarget派生出的类实现的接口得到它自己的嵌套类。
MFC使用宏BEGIN_INTERFACE_PART和END_INTERFACE_PART来产生嵌套类。
最后MFC实现了表驱动的QueryInterface。
MFC的接口映射的工作机理同它的消息映射基本相同MFC的消息映射把一个Windows消息和一个C类中的函数相联系MFC的接口映射把一个接口的GUID和一个表示此接口的特定的vptr的地址相联系。
每个基于CcmdTarget的类实现COM接口通过更多的宏DECLARE_INTERFACE_MAP BEGIN_INTERFACE_MAP INTERFACE_PART和 END_INTERFACE_MAP来增加一个接口映射。
为了理解这些宏在实际中是什么样子的请看图1它说明了实现ActiveX控件COleControl 的MFC类。
当你细读代码时注意ColeControl带有夹在一对BEGIN_INTERFACE_PART 和 END_INTERFACE_PART宏之间的每个接口的签名还要注意ColeControl的接口映射表有22个条目。
除了实现了Iunknown接口MFC还包括IclassFactory的一个标准实现。
再一次MFC通过若干宏提供了此支持。
MFC有两个宏来提供类对象DECLARE_OLECREATE_EX 和 IMPLEMENT_OLECREATE_EX.。
在一个基于CcmdTarget的类中使用这些宏增加一个ColeObjectFactory类型的静态成员到该类中。
如果你看一下AFXDISP.H中 ColeObjectFactory的定义你将会看到用在COleObjectFactory 中的MFC的嵌套类宏为实现IClassFactory2定义了一个嵌套类。
IClassFactory::CreateInstance的MFC版本使用MFC的动态创建机制DECLARE_DYNCREATE 和 IMPLEMENT_DYNCREATE宏打开此功能来实例化COM类因此买入MFC的COM支持同样意味着买入它的动态创建机制。
最后几个由MFC提供的在ActiveX控件内的基本COM支持是对Idispatch的支持。
用Visual C 和 日志标题 搜索 友情链接 美菜的blog 处理 SSI 文件时出错 其他信息 MFC实现一个分发接口几乎是微不足道的。
在MFC中实现一个分发接口只需要使用ClassWizard就可以了。
ClassWizard中的自动创建板有一个按钮用于添加属性另一个用于添加方法。
在MFC中Idispatch支持来自CcmdTarget类。
IDispatch 的MFC的实际实现在一个叫做COleDispatchImpl 的类中ColeDispatchImpl派生自Idispatch实现了所有4个Idispatch函数GetTypeInfoCount GetTypeInfo GetIDsOfNames 和 Invoke.。
由CcmdTarget派生的类通过调用EnableAutomation将IDispatch vptr加入到它们的接口映射中。
当客户在基于MFC的ActiveX控件上调用IDispatch 的QueryInterface时CcmdTarget交出链接在ColeDispatchImpl上的vptr。
每次你使用ClassWizard将一个自动属性或者方法加入到一个类中时你同时也在该类的分发映射表中加入了一项。
一个分发映射表是一个将DISPIDs用来调用分发成员的符号和它们的供人读的名字以及和实际完成这个工作的某些C代码联系起来的简单的表格。
ColeDispatchImpl的调用以及GetIDsOfNames函数通过在类的分发映射表中查找分发成员并分发DISPID相对应的函数来工作。
MFC能为某些基于COM的高级技术如OLE文档、OLE拖放和自动操作提供非常好的支持然而如果你想更改框架——比如说你想将分发接口编程双接口的——你就得大动手脚了。
另一方面ATL更加是COM中心的。
ATL的基本的COM支持 ATL的目标是使开发者不必重写IUnknown IDispatch IclassFactory和其它的分支以将常规的DLL和EXE变成基于COM的DLL和EXE。
从这个角度讲ATL是一个比MFC精简的多的框架它设计和生成时就考虑了COM支持。
它使用基于模板的方法通过继承ATL提供的模板开发者可以加入各种COM功能片断。
ATL的原始COM支持是从对Iunknown的支持开始的。
ATL的Iunknown实现分成两个部分CcomObjectRootEx类用来处理Iunknown部分的引用计数CcomObjectRootBase类用来处理QueryInterface。
CcomObjectRootEx是一个基于模板的类将线性模型作为其唯一参数。
这是一个真正有趣的说明ATL怎样使用模板将算法作为模板参数传递的例子。
ATL有两个处理引用计数的类用于处理不同的线性模型 CComSingleThreadModel 和 CcomMultiThreadModel。
这些类每个都有一个递增和一个递减函数。
它们之间的区别是CcomSingleThreadModel用标准C操作符和——实现递增和递减而CcomMultiThreadModel使用线程安全的InterlockedIncrement 和 InterlockedDecrement函数来实现这两个功能。
根据用来实例化CcomObjectRootEx的模板参数它能正确的运行给定的组件类型。
你很快将会看到它的用法的一个例子。
象MFCATL使用基于表的查找机制实现QueryInterface.。
CComObjectRootBase 通过一个接口映射处理类的QueryInterface函数。
BEGIN_ COM_MAP 和 END_COM_MAP 宏定义了一个接口映射的开始和结束。
然而不像MFCATL提供了17种途径来组成一个接口映射例如使用从ATL的基于模板的接口实现类如IOleObjectImpl 来的vptrs。
这包括了那些从tear-off 的类或者由聚合提供的类来的vptrs。
在ATL里C类通过继承CcomObjectRootEx指定它们想用的组件模型记住MFC的Iunknown支持是内建在CcmdTarget中的变成了COM类。
ATL的类对象以及IClassFactory支持也来自模板而MFC的类对象支持通过ColeObjectFactory和一些宏而有效。
ATL的类对象支持来自CComCoClass/CcomClassFactory类家族和CcomCreator类家族。
CcomCoClass包含了类的GUID定义了COM类的错误处理设施。
CcomCreator类提供了CreateInstance的实现供CcomClassFactory使用。
对于MFC你可以通过若干宏使所有这种支持有效。
ATL包括 DECLARE_CLASS_FACTORY DECLARE_CLASS_ FACTORY2 DECLARE_CLASS_FACTORY_AUTO_THREAD 以及 DECLARE_CLASS_FACTORY_SINGLETON等宏用来使各种具体的类工厂支持有效。
最后ATL 对IDispatch的支持还来自模板类——其名字是IDispatchImpl.。
比起MFC的Idispatch支持来ATL对Idispatch的支持更加是COM中心的。
MFC使用了一种hand-rolled 的IDispatch实现而ATL使用更加标准的方法来加载一个接口的类型信息并代表标准的类型库编译器。
图2显示了一个标准的基于ATL的控件。
最值得注意的一点是MFC和ATL各是怎样引入实现一个控件所需的必要的各种接口的。
MFC对标准控件接口的支持是内建在ColeControl类中的。
你从ColeControl中派生出你的控件并且一次性继承所有的函数调用。
注意ATL通过模板继承以零碎的方式逐个引入每个功能片断。
这是一个非常重要的差异因为这意味着用ATL你可以忽略一些接口实现模板例如使你的控件更为精简剥掉不希望的功能。
对MFC你不能完成同样的动作——不管你想不想你将获得所有接口。
关于例子应用 这里我将使用的例子是一个通过一个分支过程监控消息流的ActiveX控件它实时的显示消息流图。
这两个控件实际上有着相同的功能。
它们都把图表提交到屏幕。
它们都带流入接口以便包容器能通知控件开始和停止该图表。
它们都支持图表线的颜色和消息间隔长度作为属性而可以永久存在。
最后它们都支持缺省事件集将关于在一个特定时间段里处理的消息的数量通知包容器。
图3显示了这两个控件。
Figure 3 监视 ActiveX 控件消息 用MFC开发一个控件 用MFC开发一个ActiveX控件涉及到在Visual Studioampreg.中使用ActiveX ControlWizard。
为了开始一个新的控件从File菜单中选择New然后从工程类型列表中选择MFC ActiveX控件Wizard。
首先ControlWizard要求你决定在DLL中包括多少个控件。
接着你就可以选择你打算怎样实现你的控件。
ControlWizard提供的第一批选项总体上适用于控件的DLL。
它们包括了许可支持、
源码注释和在线帮助。
选择许可使得ControlWizard使用BEGIN_OLEFACTORY和END_OLEFACTORY 而非DECLARE__OLECREATE.。
BEGIN_OLEFACTORY 和 END_OLEFACTORY宏覆盖了VerifyUserLicense和GetLicenseKey因而为你的控件提供许可支持。
请求ControlWizard包括注释将所有的TODO注释加入代码中。
最后请求ControlWizard包括在线帮助将为DLL创建样板HELP文件源代码。
一旦你通过了第一个对话框ControlWizard就显示一个对话框用来配置DLL中的控件。
这些配置选择包括使控件在运行时可见的选项使得控件在可见时激活的选项使得对象可以被插入的选项给控件一个About框的选项使得控件像一个简单的框架控件那样行为的选项。
图4解释了不同的选项是如何影响ControlWizard生成的代码的。
ControlWizard还有一个将控件实现为一个标准的Windows控件的选项就像一个编辑框或者一个按钮。
这是一个有趣的选项。
例如如果你选择按照一个按钮将你的控件分成子类控件的窗口实际上是一个按钮。
此时PreCreateWindow拦截控件的窗口创建当创建控件的窗口时使用BUTTON窗口类。
ControlWizard使你可以选择一些高级的选项包括无窗口的激活使你的控件具有完整的设备上下文实现无抖动的激活使你的控件在非激活状态也接受鼠标消息使你的控件异步的加载自己的属性。
这里有一个每个选项如何影响ControlWizard生成的代码的纲要。
无窗口的激活此选项覆盖COleControl::GetControlFlags将windowlessActivate标志附加到控件标志中。
一旦使此选项有效包容器就将输入消息送交到控件的IoleInPlaceObjectWindowless接口。
此接口ColeControl的实现通过你的消息映射分发消息。
你就能通过简单的添加相应的入口到消息映射表像处理一般windows消息那样处理消息了。
无省略的设备上下文选择了此选项覆盖COleControl::GetControlFlags关闭clipPaintDC位从而在ColeControl的 OnPaint函数中去掉了IntersectClipRect调用。
如果你确定你的控件并不需要在客户区外部绘图这个选项就有用了因为使对IntersectClipRect的调用失效后有一个明显的速度的提高。
无抖动的激活选择此选项覆盖COleControl::GetControlFlags将缺省控件标志与noFlickerActivate逐位相或。
控件在激活的时候检查此标志以阻止控件在激活和非激活状态转换时被重画。
如果你的控件在激活和非激活状态外观一样那么这个选项就是有用的。
非激活时的鼠标指针通知这个选项覆盖COleControl::GetControlFlags附加了pointerInactive位。
IpointerInactive接口使得一个对象大多数时间保持非激活然而仍然参加与鼠标的某些操作的交互例如拖放。
优化的绘图码 这个选项覆盖COleControl::GetControlFlags打开canOptimizeDraw位具有优化绘图代码的控件检查这个标志通过COleControl’的IsOptimizedDraw函数来确定控件是否需要在完成绘画后将旧的对象复原回设备上下文。
异步加载属性此选项将stock ReadyState属性和stock ReadyStateChange事件加入到控件中去。
这将使得控件异步的加载其属性。
例如一个加载大量的数据作为其属性之一的控件会需要很长的时间来加载而锁住了控件。
这个stock属性和事件使得此控件立刻开始加载过程。
包容器使用此事件和属性判断控件何时完成加载。
当ControlWizard完成这些事情后你就得到了编译到一个包含此控件的DLL的源代码扩展名是.OLX。
由wizard产生的源代码包括一个从ColeControlModule它是从CwinApp中派生的中派生的类。
这个类包含整个控件模块的初始化代码。
接着wizard为基于ColeControl的表示每个控件的类生成源代码。
最后wizard生成一些ODL代码用来建立类型信息。
一旦wizard产生了控件DLL你就面临完善这个控件的任务了。
这意味着添加渲染代码开发一个引入接口方法和属性rigging up属性页展示某些事件。
但是在我向你说明所有这些都是如何工作之前我们先来看一下使用ATL创建一个控件都需要什么。
用ATL开发一个控件 有了基于MFC的控件你就可以用ATL COM App Wizard得到一个开发基于ATL的控件的触发器。
使用ATL来创建控件可以分为两步。
虽然MFC的Control Wizard要求你预先确定你希望在DLL中包含多少个控件ATL COM Wizard简单的创建DLL——你可以以后使用ATL对象选项从Insert菜单添加控件。
当创建一个新的基于ATL的DLL时你可以选择混用MFC支持。
你还可以选择在控件的DLL中合并任何proxy/stub代码。
这使得如果有人希望远程控制你的控件实现的代码你只要发布一个文件。
一旦生成了基于ATL的DLL你就可以开始添加COM类了。
Insert New ATL Object菜单条使得这项工作变得十分容易。
选择此菜单项显示一个用来创建任何一个COM类的对话框包括无格式的COM对象ActiveX控件以及Microsoft事务服务器组件Windows NT Server的一部分。
当添加基于ATL的控件到你的工程的时候ATL Object Wizard比MFC Object Wizard提供了更大范围的选项。
对于新手来说ATL使得你可以选择使用任何现有的线性模型实现你的控件。
你可以将你的类标记为或者单线程或者单元线程的。
ATL Object Wizard限制你创建一个自由的或者混合线程的控件因为控件通常是面向UI的。
如果你创建了一个单线程的控件一个包容的控件的客户将总是将它加载到主、单线程的单元STA中。
结果只有在客户进程空间运行的单主线程才会接触到你的对象这样就免除了你保护你的控件状态不受并发访问干扰的责任。
另外因为你的对象的所有实例将只会被一个线程接触你将不必担心DLL中的全局数据。
如果你的控件是单元线程的你还免除了保护你的控件的内部状态的大部分负担。
然而你仍然不得不保护DLL中的全局数据。
为什么呢首先设想你的控件是由客户的单线程创建的。
现在假定客户试图创建该控件的另一份拷贝——但是是从一个云向在当前进程的多线程的单元中。
通过将你的对象标记为单元线程的COM被告知你希望你的控件保护免遭并发访问。
COM在它加载时为你的控件创建一个新的STA。
现在当线程调用到你的对象时它们只能通过单元边界来访问它远程层将同步对此对象的调用。
然而当某个控件的状态被保护不被并发访问作为在一个STA中的副产品由控件的实例所共享的数据象在DLL中的全局数据一样是脆弱的。
这是因为你的全局DLL数据同时为几个对象服务分别运行在独立的线程中会被那些多线程同时接触到。
虽然基于MFC的COM类总是可聚合的内置了对它的支持ATL ObjectWizard使得你可以指定你的控件支持聚合只是可聚合的或者是独立的对象。
根据你选择的聚合选项ATL ObjectWizard使用一个宏来执行聚合策略。
例如缺省的COM类的实现是可聚合的——对象将既运行在独立的模式又作为一个聚合的一部分。
如果你使你的COM对象不可聚合ObjectWizard把DECLARE_NOT_ AGGREGATABLE宏加到你的类定义中。
如果你选择了仅是可聚合的ObjectWizard把DECLARE_ ONLY_AGGREGATABLE宏加入到类定义中。
这里是宏如何工作的。
缺省的对象创建在一个名为_CreatorClass的类中发生。
_CreatorClass当被加入到服务器范围的对象映射后这是OBJECT_ENTRY宏所做的工作的一部分就成为你的COM类的创建机制。
_CreatorClass其实只是一个名为CComCreator2类的别名此类将两个从CcomCreator类中定制的类作为参数。
此宏根据选择的聚合模式来特制CcomCreator类分别使用CComObject CComAggObject CComFailCreator 或者CcomPolyObject define DECLARE_NOT_AGGREGATABLEx public: typedef CComCreator2lt CComCreatorlt CComObjectlt x gt gt CComFailCreatorltCLASS_E_NOAGGREGATIONgt gt _CreatorClass define DECLARE_AGGREGATABLEx public: typedef CComCreator2lt CComCr.
上一篇:
Linux系统管理员都应该熟悉的工具
下一篇:
bc80e7a0-d1f2-4595-b21d-01a76798e87a