预览加载中,请您耐心等待几秒...
1/9
2/9
3/9
4/9
5/9
6/9
7/9
8/9
9/9

在线预览结束,喜欢就下载吧,查找使用更方便

如果您无法下载资料,请参考说明:

1、部分资料下载需要金币,请确保您的账户上有足够的金币

2、已购买过的文档,再次下载不重复扣费

3、资料包下载后请先用软件解压,在使用对应软件打开

COM组件设计与应用(十五)连接点(vc6.0)作者:HYPERLINK"mailto:good_yf@sina.com"杨老师 HYPERLINK"http://www.vckbase.com/code/downcode.asp?id=2775"下载源代码一、前言HYPERLINK"http://www.vckbase.com/document/viewdoc/?id=1525"\t"_blank"上回书介绍了回调接口,在此基础上,我们理解连接点就容易多了。二、原理图一、连接点组件原理图。左侧为客户端,右侧为服务端(组件对象)看着好复杂呀......呵呵,其实简单的紧:(注1)1、一个COM组件,允许有多个连接点对象(IConnectionPoint)。也就是说可以有多个发生“事件”的源头。上图就有3个连接点;2、管理这些连接点的接口叫“连接点容器”(IConnectionPointContainer)。连接点容器接口特别简单,因为只有2个函数,一个是FindConnectionPoint(),表示查找你想要的连接点;另一个是EnumConnectionPoints(),表示列出所有的连接点,然后你去选择使用哪个。在实际的应用中,查找法使用最多,占90%,而枚举法使用只占10%,一般在支持第三方的插件(Plugin)时才使用。(你想写个IE的插件吗?我们后面就要讲到啦)3、每一个连接点,可以被多个客户端的接收器(Sink)连接;这个我们已经熟悉啦,还记得我们在HYPERLINK"http://www.vckbase.com/document/viewdoc/?id=1525"\t"_blank"上回书中为了管理多个回调接口,使用了cookie的方式进行区别吗?!三、实现组件(一)1、建立一个工作区(WorkSpace)2、在工作区中,建立一个ATL工程(Project)。示例程序中工程名称叫Simple15,接受全部默认选项。3、ClassView中,执行鼠标右键菜单命令NewAtlObject...,添加ALT类。4、左侧分类Category选择Objects,右侧Objects选择SimpleObject(其实就是默认项目)。5、名称Name卡片中,输入组件名称。示例程序中是DispConnect。6、属性Attributes卡片中,接口类型选Dual双接口。注意一定要选择SupportConnectionPoints来支持连接点。7、ClassView中,选择接口(IDispConnect),鼠标右键菜单添加函数AddMethod...8、增加函数。和上回书的程序一样,增加一个接口函数计算加法,但通过连接点接口返回计算结果。9、下面该增加“事件”函数了。选择事件接口(_IDispConnectEvents),添加函数。10、该函数用来返回Add()函数的计算结果。11、切换到FileView卡片,编译IDL文件。当然你也可以直接编译全部工程。其实编译的目的是为了从IDL文件产生TLB文件,因为VC的IDE环境只有知道了TLB后,才能生成下面的“事件代理类的程序代码”。12、生成事件代理类程序代码。选择组件类对象(CDispConnect),执行鼠标右键菜单“实现连接点”13、选择你要让IDE帮你生成哪个连接点的代理程序代码。我们这个组件只有一个连接点,那只好选择它了。(在示例二中,我们需要实现两个连接点,那个时候,你就要选择两个了)14、到此,VC的IDE终于帮咱们完成了所有的框架,下面该咱们自己写真正的任务代码啦。 STDMETHODIMPCDispConnect::Add(longn1,longn2) { longnVal=n1+n2; Fire_Result(nVal); //调用IDE帮我们生成的代理函数代码,发出事件 returnS_OK; } 15、修正IDE产生的代码中的错误。你不用死记硬背错误点,只要编译一下就会报出错误了。一般VC6帮我们生成的代码中,有2个地方可能会有BUG。一是打开头文件,找到连接点影射宏,修改如下: BEGIN_CONNECTION_POINT_MAP(CDispConnect) CONNECTION_POINT_ENTRY(DIID__IDispConnectEvents) //修改IID_XXXX为DIID_XXXX END_CONNECTION_POINT_MAP() 这个错误简直可恨,既然我们使用的是双接口连接点,它生成的代码居然不会判断吗?另一个可能的错误可能发生在代理类中的Fire_xxxx()函数中。在示例程序中的Fire_Result()函数代码,大家自己去阅读,简单说就是循环地取得每个和自己连接对象(每个cookie表示的对象)