7.3.5控制服务器应用程序的执行客户程序控制服务器应用程序的一个方面是:必要的时候客户程序可以启动服务器程序,并装载会话主题。而客户程序控制服务器应用程序更重要的一点是向服务器发送服务器承认的宏命令,来完成对服务器应用程序的各种操作。服务器到底支持哪些宏命令,可参阅服务器应用程序文档。发送宏命令要使用DDEClientConv的两个方法ExecuteMacro和ExecuteMacroLines,它们的语法如下:functionExecuteMacro(Cmd:PChar;WaitFlag:Boolean):Boolean;functionExecuteMacroLines(Cmd:TStrings;WaitFlag:Boolean):Boolean;Cmd是欲发送的宏命令字符串或宏命令字符串链表。WaitFlag决定了在DDE服务器程序执行宏命令时客户程序的行为。如果WaitFlag设置为True,则在服务器宏命令执行完毕前,不允许对ExecuteMacro、ExecuteMacroLines、PokeData、PokeDataLines这些方法的成功调用,它们都不向服务器发送数据并返回False。如果WaitFlag设置为False,则调用的方法在第一个宏执行完毕前即试图向服务器发送数据。WaitFalg的设置也取决于服务器应用程序。一些应用程序当在第一个宏执行完之前就试图向它发送数据或命令时,可能导致第一个宏执行失败或导致不可预料的后果。具体情况可查阅服务器应用程序文档。函数返回值表示命令串是否被成功传输。而宏命令执行是否成功客户是无法检测到的。7.3.6格式化文本DDEClientConv有一个布尔属性FormartChars,用于决定是否格式化文本。所谓格式化文本是指从传输来的文本数据中过滤掉BackSpace(8)、Tab(7)、Linefeed(10)、Return(13)等字符。括号内是字符的ASCII码。许多时候这些字符将导致DDE客户数据显示的混乱。FormatChars的缺省值是False。7.3.7响应DDE事件部件DDEClientConv有两个事件OnOpen和OnClose,分别在DDE会话建立和中止时触发。部件DDEClientItem有一个OnChange事件。这一事件常用于DDE项目数据的转储和显示,如(7.3.1)节所示。在自动模式下,OnOpen事件在包含DDEClientConv部件的窗口创建时触发,或在调用SetLink方法时触发,OnClose事件在客户程序或服务器程序关闭时触发。在人工模式下,OnOpen事件在调用OpenLink方法时触发,OnClose事件在调用ColseLink方法时触发。7.3.8利用客户程序和Excel交换数据下面我们建立一个DDE客户程序,并利用这一程序与Excel中的一个工作表交换数据。程序设计界面界面中包含一个DDE会话部件DDEClientConv1和DDE项目部件DDEClientItem1,用于建立和维护DDE联接;一个RadioGroup控件和其中的两个无线电按钮AutoRadio、ManualRadio,用于设置联接模式;一个GroupBox控件和其中的两个按钮RequestBtn和PokeBtn,用于控制数据的申请和发送,其中RequestBtn在自动模式下变灰;一个文本框Memo1用于保存DDE数据;一个按钮PasteBtn用于粘贴联接信息并建立DDE联接;另外一个按钮CloseBtn用于关闭系统。设计时把DDEClientConv1的FormatChars属性置为True,这样可以保留服务器传来数据的显示格式;ConnectMode保留ddeAutomatic的缺省设置。程序在类TForm1中定义了一个私有数据成员Automatic,用于标志联接模式;三个字符串数据成员DDEService、DDETopic、DDEItem用于记录联接信息。窗口生成时进行变量和部件状态的初始化。procedureTForm1.FormCreate(Sender:TObject);beginRequestBtn.Enabled:=False;AutoRadio.Checked:=True;Automatic:=True;end;当联接模式改变时,程序进行相应的处理。自动模式转换为人工模式:procedureTForm1.ManualRadioClick(Sender:TObject);beginifAutomaticthenbeginRequestBtn.Enabled:=ManualRadio.Checked;DDEClientConv1.ConnectMode:=ddeManual;Automatic:=False;end;end;人工模式转换为自动模式:procedureTForm1.AutoRadioClick(Sender:TObject);beginifnotAutomaticthenbeginRequestBtn.Enabled:=ManualRadio.Checked;If(DDEService='')or(DDETopic='')thenbeginMessageDlg('CannotSetLink.',mtWarning,[mbOK],0);Exit;end;DDEClientConv1.SetLink(DDEService,DDETopic);DDEClientItem1.DdeConv:=DDEClientConv1;DDEClientItem1.DDEItem:=DDEItem;DDEClientConv1.ConnectMode:=ddeAutomatic;Automatic:=True;end;end;当从自动模式转换到人工模式,只需要简单修改相应属性即可;而从人工模式转换到自动模式,则需要调用SetLink重新建立联接,否则往往会引发一个DDE异常。联接的建立采用从剪贴板粘贴联接信息的方式,这是最具有灵活性的一种方法。procedureTForm1.PasteBtnClick(Sender:TObject);beginifGetPasteLinkInfo(DDEService,DDETopic,DDEItem)thenbeginDDEClientConv1.SetLink(DDEService,DDETopic);ifAutomaticthenbeginDDEClientItem1.DdeConv:=DDEClientConv1;DDEClientItem1.DDEItem:=DDEItem;end;end;end;GetPasteInfo是DDEMan库单元中定义的一个函数,用于检测剪贴板上是否有联接信息并返回相应的DDE服务、主题和项目。对于人工模式,必须由客户显式向服务器申请数据。在这种模式下DDE项目部件是多余的,接收到的DDE联接信息用一个字符串来记录。下面是实现代码。procedureTForm1.RequestBtnClick(Sender:TObject);varTheData:PChar;beginIfDDEItem=''thenbeginMessageDlg('CannotRequestData',mtWarning,[mbOK],0);Exit;end;TheData:=StrAlloc(79);DDEClientConv1.OpenLink;TheData:=DDEClientConv1.RequestData(DDEItem);DDEClientConv1.CloseLink;ifTheDatanilthenMemo1.Text:=StrPas(TheData);StrDisPose(TheData);end;OpenLink、CloseLink方法用于打开和关闭联接。RequestData方法向服务器申请数据并返回到一个PChar字符串中。字符串必须显式分配内存并在退出时释放。数据发送在不同联接模式下是不同的。对于人工模式,增加了联接的打开和关闭操作。程序清单如下。procedureTForm1.PokeBtnClick(Sender:TObject);beginIfDDEItem=''thenbeginMessageDlg('CannotPokeData.',mtWarning,[mbOK],0);Exit;end;ifAutomaticthenDDEClientConv1.PokeDataLines(DDEItem,Memo1.Lines)elsebeginDDEClientConv1.OpenLink;DDEClientConv1.PokeDataLines(DDEItem,Memo1.Lines);DDEClientConv1.CloseLink;end;end;打开MicrosoftOffice中的Excel,装入一个文件,把相关的单元选中,拷贝到剪贴板上。而后运行程序,按下PasteLink按钮,DDE联接就建立起来,相关单元中的数据显示在Memo1中。之后可以进行模式转换、数据申请、申请发送等一系列工作。运行后的屏幕显示如下图所示。7.3.9用客户程序控制程序管理器下面的例子用客户程序向程序管理器发送命令,用于创建程序组、程序项以及删除程序组。程序管理器提供了应用程序的DDE接口命令字符串,应用程序利用这些命令字符串可以实现以下的功能:1.创建程序组命令格式为:CreateGroup(程序组名[,程序组所在的路径])程序组不存在时进行创建;如程序组存在则按照指定的路径激活。2.删除程序组命令格式为:DeleteGroup(程序组名)3.显示程序组命令格式为;ShowGroup(程序组名,显示标志)显示标志用于控制程序组在程序管理器中以极大、极小或正常方式显示。4.重新装入程序组命令格式为:ReLoadGroup(程序组名)该命令使程序管理器先删除而后再重新装入一个已有的程序组。5.向程序组中添加程序项命令格式为:AddItem(命令行[,描述[,图标路径[,图标序号[,图标横坐标,图标纵坐标[,工作区目录[,热键[,是否最小化显示标志]]]]]]])命令行控制程序项的执行,可包括路径、参数等。其它参数分别对应在程序管理器中添加一个程序项时需要设置的参数和选项。它们都有缺省设置,因而是可选的。6.替换程序组中的程序项命令格式为:ReplaceItem(程序项名)该命令删除一个程序项,并将所删除程序项的位置记录下来,以后通过AddItem在这个所记录的位置增加新项目。7.从程序组中删除程序项命令格式为:DeleteItem(程序项名)从当前活动程序组中删除一个程序项。8.关闭程序管理器命令格式为:ExitProgram(是否保存程序组信息标志)从应用程序向程序管理器发送命令字符串的方法是基本一致的。为简便起见,在例程中只实现了其中仅包含一个字符串参数的情形,读者可以很容易作进一步的扩展。程序设计界面如图所示,包含一个DDE客户会话(DDEClientConv)部件和四个完成不同功能的按钮。DDEClientConv在设计时和程序管理器建立一个DDE会话,其中DDE服务器和DDE主题都为PROGMAN。联接模式ConnectMode设置为ddeManual。我们把只有一个字符串参数的命令发送情况抽象出来,形成下面的SendMacro函数。functionTForm1.SendMacro(Name:String;Command:String):Boolean;varMacro:String;Cmd:array[0..255]ofChar;beginResult:=True;ifName''thenbeginMacro:=Format('['+Command+'(%s)]',[Name])+#13#10;StrPCopy(Cmd,Macro);DDEClient.OpenLink;ifnotDDEClient.ExecuteMacro(Cmd,False)then