简介
在Windows、OS/2、以及其他的一些操作系统(带有第三方的开发工具)上,动态数据交换(Dynamic Data Exchange,DDE)允许数据在程序间被共享或者通信。例如,当你在你的数据库程序中改变一个表,或者电子制表软件中的数据项时,则这个表或者数据项也需要在你可能使用的其他软件中进行相应的改变。DDE是使用共享内存作为公共交换区域并提供应用程序一个协议或者命令集以及消息格式的进程间通信。DDE使用了客户端/服务器模型,在这个模型中,应用程序对数据的请求在客户端进行处理,同时应用程序对数据的提供在服务器端处理。1
工作原理DDE的工作原理是:
两个同时运行的程序间通过DDE方式交换数据时是客户/伺服器关系,一旦客户和伺服器建立起来连接关系,则当伺服器中的数据发生变化后就会马上通知客户。通过DDE方式建立的数据连接通道是双向的,即客户不但能够读取伺服器中的数据,而且可以对其进行修改。
DDE和剪贴板一样既支持标准数据格式(如文本、点阵图等),又可以支持自定义的数据格式。但它们的数据传输机制却不同,一个明显区别是剪贴板操作几乎总是用作对用户指定操作的一次性应答,如从菜单中选择粘贴命令。尽管DDE也可以由用户启动,但它继续发挥作用,一般不必用户进一步干预。
例如:
甲方申请一块全局内存,然后把内存指针postmessage到乙方,乙方根据收到的指针访问那块全局内存。有几个API函数是做这种事的,你在MSDN里查一下 Dde 打头的函数全都出来了。因为是已经淘汰的技术,连MFC都没对他进行封装。很难保证它同样会出现在以后的Windows API中2。
内容DDE对话的内容是通过三个标识名来约定的。
1、应用程序名:进行DDE对话的双方的名称。商业应用程序的名称在产品文档中给出。“组态王”运行系统的程序名是“VIEW”;Microsoft Excel的应用程序名是“Excel”;Visual Basic程序使用的是可执行文件的名称。
2、主题:被讨论的数据域(domain)。对“组态王”来说,主题规定为“tagname”;Excel的主题名是电子表格的名称,比如sheetl,sheet2,……;Visual Basic程序的主题由窗体(Form)的LinkTopic属性值指定。
3、项目:这是被讨论的特定数据对象。在“组态王”的数据词典里,工程人员定义I/O变量的同时,也定义项目名称。Excel里的项目是单元,比如rlc2(rlc2表示第一行、第二列的单元)。对Visual Basic程序而言,项目是一个特定的文本框、标签或图片框的名称3。
交换方式(1)冷连接(CoolLink):数据交换是一次性数据传输,与剪贴板相同。当服务器中的数据发生变化后不通知客户,但客户可以随时从服务器读写数据;
(2)温连接(WarmLink):当服务器中的数据发生变化后马上通知客户,客户得到通知后将数据取回;
(3)热连接(HotLink):当服务器中的数据发生变化后马上通知客户,同时将变化的数据直接送给客户。
DDE客户程序向DDE服务器程序请求数据时,它必须首先知道服务器的名称(即DDEService名)、DDE主题名称(Topics名),还要知道请求哪一个数据项的项目名称(Items名)。DDEService名应该具有唯一性,否则容易产生混乱。通常DDEService就是服务器的程序名称,但不是绝对的,它是由程序设计人员在程序内部设定好的,并不是通过修改程序名称就可以改变的。Topics名和Items名也是由DDEService在其内部设定好的,所有服务程序的Service名、Topics名都是注册在系统中,当一个客户向一个服务器请求数据时,客户必须向系统报告服务器的Service名和Topics名。只有当Service名、Topics名与服务器内部设定的名称一致时,系统才将客户的请求传达给服务器。
当服务名和Topics名相符时,服务器马上判断Items名是否合法。如果请求的Item名是服务器中的合法数据项,服务器即建立此项连接,建立连接的数据发生数值变化后,服务器会及时通知客户。一个服务器可以有多个Topics名,Items名的数量也不受限制。
DDE交换可以发生在单机或网络中不同计算机的应用程序之间。开发者还可以定义定制的DDE数据格式,进行应用程序之间特别目的IPC,它们有更紧密耦合的通信要求。大多数基于Windows的应用程序都支持DDE。但DDE有个明显的缺点就是,通信效率低下,当通信量较大时数据刷新速度慢,在数据较少时DDE较实用。
编写程序为了使用方便起见,微软提供DDE管理库(TheDDEManagementLibrary,简称DDEML)。DDEML专门协调DDE通信,给DDE应用程序提供句柄字符串和数据交换的服务,消除了早期由于DDE协议不一致所引起的问题。
使用DDEML开发的应用程序(客户/服务器)无论在运行一致性方面,还是在程序相互通信方面,性能均优于没有使用DDEML的应用程序。而且DDEML的应用使得开发支持DDE的应用程序容易了许多,因为DDEML(这是个DLL)担起了内务府总管的工作。使用DDEML后,实际上客户和服务器之间的多数会话并不是直达对方的,而是经由DDEML中转,即用Callback函数处理DDE交易(Transaction),而早期的消息通信是直接的。
在调用其他DDEML函数前,客户/服务器必须调用DdeInitialize()函数,以获取实例标识符,注册DDECallback函数,并为Callback函数指定事务过滤。对于服务器,在使用DdeInitialize()初始化后,调用DdeCreateStringHandle()建立Service名、Topics名和Items名等标识的句柄,再通过DdeNameService()在操作系统中注册服务器的名字。根据这些句柄,客户就可以使用它提供的DDE服务了。
为了执行某个DDE任务,许多DDEML函数需要获得字符串的访问权。例如:一个客户在调用DdeConnect()函数来请求同服务器建立会话时,必须指定Service名和Topics名。可以通过调用DdeCreateStringHandle()函数来获取特定字符串句柄。例如:
HSZhszServName=DdeCreateStringHandle(idInst,"MyServer",CP_WINANSI);
HSZhszSysTopic=DdeCreateStringHandle(idInst,SZDDESYS_TOPIC,CP_WINANSI);
一个应用程序的DDE回调函数在大多DDE事务中接收多个字符串句柄。比如:在XTYP_REQUEST事务处理期间,一个DDE服务器接收两个字符串句柄:一个标识Topics名字符串,另一个标识Items名字符串。可以通过调用DdeQueryString()函数来获取相应于字符串句柄的字符串长度,并且复制字符串到应用程序定义的buffer中。例如:
DWORDidInst;
DWORDcb;
HSZhszServ;
PSTRpszServName;
cb=DdeQueryString(idInst,hszServ,(LPSTR)NULL,0,CP_WINANSI)+1;
pszServName=(PSTR)LocalAlloc(LPTR,(UINT)cb);
DdeQueryString(idInst,hszServ,pszServName,cb,CP_WINANSI);
根据微软MSDN,现有的基于消息DDE协议的应用程序与DDEML应用程序是相容的,也就是说,基于消息通信的DDE应用程序可以与DDEML应用程序对话和交易。在使用DDEML时,必须在源程序文件中包括ddeml.h头文件,连接user32.lib文件,并保证ddeml.dll文件正确的系统路径。