摘要
动态数据交换(DDE,Dynamic data exchange)是Microsoft Windows运行环境下的一个显著特性。通过动态数据交换协议,应用程序之间可以进行各种类型的数据交换。动态数据交换还允许应用程序建立与DDE服务器的热链接从而可以实时地获取数据。热链接可以完成从一个应用程序(DDE服务器)到另一个应用程序(DDE客户机)之间的直接数据传递。当位于服务器上的数据发生了变化,服务器就会发送一条信息给客户机等待处理。
本文介绍了如何通过在对话框中浏览DDE服务器来建立热链接,同时也阐述了当一个应用程序重启动后,再次建立热链接时所需要的过程。
本文通过一个应用程序示例说明了如何建立链接以及当一个应用程序重启动后如何再次建立链接。
介绍
自从Microsoft Windows 2.1版发布以来,动态数据交换(DDE)就已经成为Windows的一部分,并且许多应用程序都采用了DDE技术,DDE作为一种基本机制已经应用于对象链接与嵌入(OLE,Object Linking and Embedding)的1.0版中。但实现完全的DDE协议并不是非常容易的事情,不同的开发者对协议规约的解释也略有不同。
近来推出的动态数据交换管理库(DDEML,Dynamic Data Exchange management Library)中提供了DDE函数集和应用程序级协议。使用DDEML开发的应用程序无论在运行一致性方面还是在应用程序相互通信方面性能均优于没有使用DDEML的应用程序。而且DDEML的应用使得开发支持DDE的应用程序容易了许多。
尽管如此,要完全地实现动态数据交换也还是有许多工作要做的。文章中给出了为完成此项工作所需要的一些约定以及一个应用程序的样代码,这些样代码可以直接拿过来用于自己的应用程序中,所有这些同时也说明了一个问题,DDE在许多应用程序中得到了普遍的支持,如Microsoft Excel软件。
另外,文中假定所有的动态数据交换是通过DDEML接口实现的。
服务器和服务名
此处的服务器指的是一个能提供一种或多种DDE服务的应用程序。而服务名是指由服务器提供的DDE服务的名称。一个服务器可以提供一种或多种服务。通常情况下,一个服务器只提供一种服务,并且服务器的名字与它所提供的服务的名称(即服务名)相同,这种做法对于重新连接会话非常有利。例如服务器还没有启动某项服务,那么客户端就可以根据服务名推断出应用程序名(即服务器名)。
如果你要创建DDE服务器,那么最好让服务器只支持一种服务,并且将服务器与服务的命名一致。如果你一定坚持要一个服务器支持多种服务,那么你就需要给其他的应用程序使用者提供服务名列表。
Microsoft Excel软件中就假定服务器的名字和服务名相同。
浏览连接
在DDE服务器应用程序(如Microsoft Excel)的用户文档中有所支持的服务主题的列表。为了将客户应用程序连接到服务器,用户需要选择服务名(通常与服务器名相同)、服务主题名以及所感兴趣的主题项名。
DDE服务器如果支持System(系统)主题,那么就可以对主题清单和每一个主题所支持的主题项清单进行询问。有了这项功能,用户就可以通过DDE客户应用程序显示出的对话框,浏览当前注册的各项DDE服务,并且可以通过鼠标选择相应的服务(service)、主题(topics)以及主题项(items)进而完成与服务器的连接。
并不是每一个服务器都支持System服务主题,即使是支持System服务主题的服务器,通常也不会实现全部的主题及主题项,所以需要在对话框中能够直接键入服务名、主题名以及项名。
连接对话框
图1:DDERecon的连接对话框
图1所示为应用程序示例DDERecon的连接对话框。对话框中左侧的列表框中列出了当前注册的DDE服务。图中含有两项DDE服务:StockSrv(Stock Service)和WinWord(Microsoft Word for Windows)。其中StockSrv被选中,在中间的列表框中则列出了相应于StockSrv服务的可用主题。由于StockSrv服务支持System主题,所以在Service Topics的列表框中列出了该主题。因为包含System主题信息对于绝大多数终端用户的意义并不大,所以在对话框代码中设计了切换代码,可以忽略这项信息,从而使得对话框更加清晰明了。
图2:忽略System项的连接对话框
图2所示的创建DDE链接的对话框与图1的不同之处在于图2中忽略了System主题和System项。中间的列表框中,仅有Prices主题,且被选中,右侧的列表框则列出了相应与Prices主题的可用项。注意图1中“Formats”和“TopicItemList”项是服务器的System主题所支持的项,在选择Suppression(禁止)项时被排除在外。DDERecon示例的菜单中包含了一个打开/关闭System(系统)信息显示的选项。
重新建立DDE链接
当DDE客户应用程序重启动后,如果想通过DDE请求从DDE服务器中获取数据,那么就不得不重新建立与DDE服务器的会话。
下面让我们看一下重新建立链接所需要的步骤。
需要链接吗?
开发者可以开发一应用程序,不需要进行询问就直接重建DDE会话的连接。这种自动连接方式在许多情况下是很方便的,但是个别情况下就显得很不方便,如开发者正在为应用程序录制一系列处理DDE数据的宏,他并不想在录制过程中建立链接。另外,如果启动一个应用程序只是想查看一下数据在上一次使用时的状态而并不关心数据的当前状态时,这种自动连接方式也是很不方便的。
图3:请求重建特定链接的对话框
图3所示的是一个DDERecon应用程序示例中所使用的询问用户是否需要重建链接的消息框。图3所示的消息框让用户决定是否需要重建某一服务的特定主题/项的链接。在许多应用程序中都含有不只一个热链接,在这种情况下,最好能提供一个消息框,询问用户是否重建所有的热链接,而不是逐一地进行询问。图4所示的是Microsoft Excel所使用的询问是否重建所有的热链接的对话框。
图4:请求重建所有的热链接的对话框
需要说明的是图4所示的对话框中含有一帮助(help)按钮,这并不多余,设想大多数终端用户可能对“Remote link”并不理解,这时就可以选择帮助按钮以获取帮助。
服务器是活动的吗?
为了确定DDE用户所需要的服务器是否处于活动状态,客户应用程序可以通过调用函数DdeConnect发出一个连接请求,这里需要给出服务名(该服务中至少包含一个所支持的主题),而并不需要主题名。如果服务器处于活动状态,连接请求成功。客户应用程序就可以继续发出实际主题的连接请求,从而获得所关心的主题项的当前值,最后再发出主题项的建议请求(advise request),就可以获取项数据的更新信息。
一个应用程序可以直接根据某一主题名而不是空主题来申请建立某一主题的链接,从而将服务器状态的检测和链接的重建结合在一起。当应用程序直接按照名字链接时,如果链接请求失败,要求服务器重启动,那么一定要注意一下返回的错误代码。DDERecon应用程序示例是按两步进行连接的。 如果服务器处于非活动状态,用户的服务请求无法实现时,应用程序可能要询问用户是否想通过客户应用程序来重新启动服务器。DDERecon示例中使用的询问对话框如图5所示。
启动服务器
图5:请求重新启动服务器的对话框
如果用户在图5所示的对话框中选择了“Yes”,DDERecon将试图运行服务器应用程序。由于所感兴趣的主题名可能与服务器为响应用户的请求而打开需要的文档同名,所以DDERecon在服务器应用程序名的后面直接附加了一个主题名,然后再发出执行请求。假如现在DDERecon要启动服务器STOCKSRV.EXE中的“Prices”主题,则相应的函数调用如下:
WinExec(”STOCKSRV.EXE Prices”,SW_SHOWNOACTIVATE);
Microsoft Excel就是按照这种方式启动DDE服务器应用程序的。当Microsoft Excel进行响应时,它根据命令行中的第一个参数给出的服务名和主题名打开相应的文件。命令行参数的使用并不影响动态数据交换,它只是应用程序的一种调用方式。如果使用DDERecon应用程序查看Microsoft Excel,你就会看到一主题列表框,里面包含了打开文件的完整路径。
另外,DDERecon应用程序在通过WinExec函数启动服务器应用程序时,使用了参数SW-SHOWNOACTIVATE,所以服务器启动后并没有立即处于活动状态。在这里需要注意的是,DDERecon应用程序在调用WinExec函数前,要先调用函数SetWindowPos,通过HWND_TOPMOST参数使DDERecon应用程序窗口位于最顶层,当WinExec函数调用结束后,DDERecon应用程序将再次调用函数SetWindowPos,这一次再使用参数HWND_NOTOPMOST。在调用WinExec函数前将DDERecon应用程序窗口位于最顶层可以防止服务器应用程序启动后,它的窗口将DDERecon窗口覆盖掉。有关WinExec函数的详细信息,请参见微软网络开发光盘中的“Ask Dr. GUI #4”部分里面的“Z-Order Changes with WinExec”介绍。
当服务器启动后,它要注册DDE服务名,并且要完成第一次函数GetMessage调用前的初始化工作。WinExec函数调用结束后,DDERecon应用程序就可以立即与服务器上的注册服务建立连接。
使用函数WinExec或LoadModule来启动应用程序可能存在一个问题,就是应用程序有可能并不在Windows的搜索路径下。我们知道,在安装应用程序时,通常是将应用程序安装在以应用程序名字命名的目录下,比如将Microsoft Excel程序安装在Microsoft Excel目录下,而且不能把创建的目录置于MS-DOS路径下,因为MS-DOS路径名长度是有限制的。
DDERecon应用程序示例假定服务器应用程序位于Windows的搜索路径下。在函数WinExec调用失败的情况下,DDERecon会弹出一个消息框,如图6所示。
图6 :WinExec调用失败时的消息框
对于使用者,如果出现上述的消息框,可能会感到莫名其妙,找不到问题所在。在这种情况下,你可以阅读微软网络开发光盘中技术部分中的“Launching Other Windows-Based Applications”,以找到解决问题的方法。
获取数据
服务器启动以后,DDERecon应用程序就能够通过调用函数DdeConnect建立与服务器有关主题的对话,然后再调用函数DdeClientTransaction,使用XTYP_REQUEST选项,获取所需主题项的当前状态。为了完全地实现热链接,DDERecon应用程序还需要最后调用一次函数DdeClientTransaction,使用XTYP_ADVSTART选项,建立一个与项的呼叫请求。所有这些工作做完之后,服务器就会在每次项数据发生变化时发送数据到DDERecon应用程序,而客户端则通过DDE回调函数,利用XTYP_ADVDATA选项接收数据。
友好地面向用户
对于开发者而言,在浏览DDE服务器方面以及建立与服务器的热链接方面可能存在一些小的技术难题,而对于使用者而言,可能会遇到一些有关DDE模糊不清的问题。所以在将动态数据交换(DDE)并入自己的应用程序中时,一定要尽可能多的为使用者考虑。要确保使用者清楚如何操作,理解为什么要这样操作,会有什么样的结果,比如选定某一按钮、在对话框中输入文本或者响应消息框。而且对于出现的错误信息报告要做到清晰、明确,这一点很重要,好的错误信息报告让使用者一看就知道发生了什么错误。