DDE
热链接
Herman Rodent
微软网络技术开发组
>
摘要
动态数据交换(
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
)并入自己的应用程序中时,一定要尽可能多的为使用者考虑。要确保使用者清楚如何操作,理解为什么要这样操作,会有什么样的结果,比如选定某一按钮、在对话框中输入文本或者响应消息框。而且对于出现的错误信息报告要做到清晰、明确,这一点很重要,好的错误信息报告让使用者一看就知道发生了什么错误。