nk方法用于打开和关闭联接。RequestData方法向服务器申请数据并返回到一个PChar字符串中。字符串必须显式分配内存并在退出时释放。
数据发送在不同联接模式下是不同的。对于人工模式,增加了联接的打开和关闭操作。程序清单如下。
procedure TForm1.PokeBtnClick(Sender: TObject); begin If DDEItem = '''''''' then begin MessageDlg(''''Can not Poke Data.'''',mtWarning,[mbOK],0); Exit; end; if Automatic then DDEClientConv1.PokeDataLines(DDEItem,Memo1.Lines) else begin DDEClientConv1.OpenLink; DDEClientConv1.PokeDataLines(DDEItem,Memo1.Lines); DDEClientConv1.CloseLink; end; end;
打开Microsoft Office中的Excel,装入一个文件,把相关的单元选中,拷贝到剪贴板上。而后运行程序,按下Paste Link按钮,DDE联接就建立起来,相关单元中的数据显示在Memo1中。之后可以进行模式转换、数据申请、申请发送等一系列工作。运行后的屏幕显示如下图所示。
图7.3 DDE客户和Excel交换数据
7.3.9 用客户程序控制程序管理器
下面的例子用客户程序向程序管理器发送命令,用于创建程序组、程序项以及删除程序组。
程序管理器提供了应用程序的DDE接口命令字符串,应用程序利用这些命令字符串可以实现以下的功能:
1.创建程序组
命令格式为:
CreateGroup(程序组名[,程序组所在的路径])
程序组不存在时进行创建;如程序组存在则按照指定的路径激活。
2.删除程序组
命令格式为:
DeleteGroup(程序组名)
3.显示程序组
命令格式为;
ShowGroup(程序组名,显示标志)
显示标志用于控制程序组在程序管理器中以极大、极小或正常方式显示。
4.重新装入程序组
命令格式为:
ReLoadGroup(程序组名)
该命令使程序管理器先删除而后再重新装入一个已有的程序组。
5.向程序组中添加程序项
命令格式为:
AddItem(命令行[,描述[,图标路径[,图标序号[,图标横坐标,图标纵坐标[,工作区目录[,热键[,是否最小化显示标志]]]]]]])
命令行控制程序项的执行,可包括路径、参数等。其它参数分别对应在程序管理器中添加一个程序项时需要设置的参数和选项。它们都有缺省设置,因而是可选的。
6.替换程序组中的程序项
命令格式为:
ReplaceItem(程序项名)
该命令删除一个程序项,并将所删除程序项的位置记录下来,以后通过AddItem在这个所记录的位置增加新项目。
7.从程序组中删除程序项
命令格式为:
DeleteItem(程序项名)
从当前活动程序组中删除一个程序项。
8.关闭程序管理器
命令格式为:
ExitProgram(是否保存程序组信息标志)
从应用程序向程序管理器发送命令字符串的方法是基本一致的。为简便起见,在例程中只实现了其中仅包含一个字符串参数的情形,读者可以很容易作进一步的扩展。
程序设计界面如图所示,包含一个DDE客户会话(DDEClientConv)部件和四个完成不同功能的按钮。
图7.4 控制程序管理器应用程序的设计界面
DDEClientConv在设计时和程序管理器建立一个DDE会话,其中DDE服务器和DDE主题 都为PROGMAN。联接模式ConnectMode设置为ddeManual。
我们把只有一个字符串参数的命令发送情况抽象出来,形成下面的SendMacro函数。
function TForm1.SendMacro(Name: String;Command: String): Boolean; var Macro: String; Cmd: array[0..255] of Char; begin Result := True; if Name <> '''''''' then begin Macro := Format(''''[''''+Command+''''(%s)]'''', [Name]) + #13#10; StrPCopy (Cmd, Macro); DDEClient.OpenLink; if not DDEClient.ExecuteMacro(Cmd, False) then Result := False; DDEClient.CloseLink; end; end;
过程首先利用Format函数形成宏字符串:
Macro := Format(''''[''''+Command+''''(%s)]'''', [Name]) + #13#10;
而后把Pascal类型的字符串拷贝到一个程序管理器可接受的PChar类型字符串中。 DDE联接采用人工模式。首先调用OpenLink方法。而后调用ExecuteMacro方法发送命令,如失败则返回False。最后用CloseLink关闭联接。
三个按钮CreateButton、AddButton、DeleteButton分别用于创建程序组、添加程序项、删除程序组。它们的程序实现大同小异,如下所示。
创建程序组:
procedure TForm1.CreateButtonClick(Sender: TObject); var Name: String; begin Name := InputBox(''''Input Box'''',''''Input Group Name'''',''''''''); if Name = '''''''' then MessageDlg(''''Group name can not be blank.'''', mtError, [mbOK], 0) else if SendMacro(Name,''''CreateGroup'''') = False then MessageDlg(''''Unable to create group.'''', mtInformation, [mbOK], 0); end;
添加程序项:
procedure TForm1.AddButtonClick(Sender: TObject); var Name: String; begin Name := InputBox(''''Input Box'''',''''Input Application full_Path name'''',''''''''); if Name = '''''''' then MessageDlg(''''Application name can not be blank.'''', mtError, [mbOK], 0) else if SendMacro(Name,''''AddItem'''') = False then MessageDlg(''''Unable to Add Item.'''', mtInformation, [mbOK], 0); end;
删除程序组:
procedure TForm1.DeleteButtonClick(Sender: TObject); var Name: String; begin Name := InputBox(''''Input Box'''',''''Input Group Name to be Deleted'''',''''''''); if Name = '''''''' then MessageDlg(''''Group name can not be blank.'''', mtError, [mbOK], 0) else if SendMacro(Name,''''DeleteGroup'''') = False then MessageDlg(''''Unable to create group.'''', mtInformation, [mbOK], 0); end;
7.4 DDE服务器程序的实现
DDE服务器程序响应DDE客户的请求,一般地它包含了客户程序希望获取的数据。 创建一个DDE服务器程序,必须要把一个DDEServerItem部件添加到窗体中。DDEServerItem的text或Lines属性包含了要联接的数据。一般地 DDEServerItem部件又和另一个文本控件相联系。当文本控件中的内容变化时则更新DDEServerItem 的text或Lines属性的值。下面的一段程序把DDEServerItem和一个列表框相联系。这一联系是在列表框的OnChange事件中实现。
procedure Form1.OnListBoxChange(Sender: TObject); begin DDEServerItem1.Lines := ListBox1.Items; end;
创建DDE服务器程序时也可以再加入一个DDEServerConv部件,并把两个部件利用DDEServerItem的ServerConv属性联系起来。此时DDE主题成为部件DDEServerConv的名称,而不是拥有DDEServerItem部件窗体的标题。
在下列情况下使用DDEServerConv部件成为必要:
1.拥有DDEServerItem 部件窗体的标题可能在运行时改变或可能有其它窗体拥有同样的标题。在这种情况下DDE联接可能无法建立;
2.DDE客户程序可能会向你的服务器程序发送一条宏命令。在这种情况下只有拥有一个DDEServerConv部件才能响应OnMacroExecute事件并执行相应的动作。
7.4.1 和DDE客户程序建立联接
一般说来,建立DDE联接是客户程序的任务。但服务器程序可以把一个联接拷贝到剪贴板上供客户程序粘贴并建立DDE会话。步骤如下:
1.调用DDEServerItem部件的CopyToClipboard方法, 把Text(或Lines)属性的值和DDE联接信息拷贝到剪贴板上;
2.DDE客户程序插入联接的数据。一般地这是通过选择适当的命令(如Edit|Paste Special或Edit|Paste Link)来实现的。
7.4.2 响应DDE事件
部件DDEServerConv有三个事件:OnOpen、OnClose、OnExecuteMacro。前两个事件在DDE会话建立和终止时触发。同(7.3.7)中的介绍。
OnExecuteMacro事件用于响应客户程序发送过来的宏指令。OnExecuteMacro事件处理过程有一个Msg参数,保存发送过来的指令串。用户可以在该过程中决定如何响应这些宏指令。
DDEServerItem部件只有一个事件OnPokeData。这一事件用于响应客户程序发送来的数据。如果客户程序是Delphi程序,则客户程序调用了PokeData或PokeDataLines方法。在这一事件的处理过程中用户可以把发送来的数据保存到一个合适的地方。一般说来这应该就是DDEServerItem所联系的文本控件。
下面的程序把发送来的数据保存到ListBox中。
procedure Form1.OnDDEServerItemPokeData(Serder: TObject); begin ListBox1.Items := DDEServerItem1.Lines; end;
7.4.3 DDE服务器应用例程
下面我们创建一个DDE服务器例程和一个相应的DDE客户例程。
DDE服务器例程可以完成的工作有:
1.把DDE联接信息拷贝到剪贴板上供其它程序使用; 2.利用一个TMemo部件为其它程序提供数据源; 3.接收客户程序发送来的数据; 4.根据客户程序发送来的宏指令改变自身的运行状态。
服务器例程的设计界面如图。
图7.5 服务器例程设计界面
其中各部件的关键属性如下:
DDESrvrForm.ActiveControl = Memo1 DDESrvrForm.Menu = MainMenu1 Bevel1.Align = alTop Memo1.Align = alClient DDETestItem.ServerConv = DDETestTopic
通过设置Bevel1、Memo1的Align属性,可以保证窗口大小变化时仍能有较为美观的屏幕显示。 Memo1是服务器的数据源,DDE项目部件DDETestItem通过Memo1的OnChange事件与Memo1 建立联系。
procedure TDdeSrvrForm.doOnChange(Sender: TObject); begin if not FInPoke then DDETestItem.Lines := Memo1.Lines; end;
其中FInPoke是一个布尔类型的私有数据成员,用于标志程序是否在处理客户程序的数据发送。当数据是由客户发送过来转存到数据源时,则没有必要再把数据传给DDE项目部件。
把联接信息拷贝到剪贴板,只需简单调用DDETestItem的CopyToClipboard方法。 procedure TDDESrvrForm.CopyClick(Sender: TObject); begin DDETestItem.CopyToClipboard; end;
这是通过菜单项Edit|Copy来调用的。
接收客户程序发送来的数据,是在DDETestItem的OnPokeData事件处理过程中。在接收过程中改变FInPoke的值,以阻止数据的无效反送。
procedure TDDESrvrForm.doOnPoke(Sender: TObject); begin FInPoke := True; Memo1.Lines := DDETestItem.Lines; FInPoke := False; end;
在DDE会话部件DDETestTopic的OnExecuteMacro事件处理过程中处理客户发送来的宏指令。我们共定义了五种可以响应的宏指令:CopyDDE、Clear、WS_Normal、WS_MINIMIZED、WS_MAXIMIZED,分别用于拷贝联接信息、清除Memo1中的内容以及改变窗口显示状态。
procedure TDdeSrvrForm.doMacro(Sender: TObject;Msg: TStrings); var Cmd: String; i: Integer; begin Cmd := ''''''''; if Msg.Count = 0 then Exit; for I := 0 to Msg.Count-1 do begin Cmd := Msg.Strings[i]; if UpperCase(Cmd) = ''''COPYDDE'''' then DDETestItem.CopyToClipboard else if UpperCase(Cmd) = ''''CLEAR'''' then Memo1.text: = '''''''' else if UpperCase(Cmd) = ''''WS_NORMAL'''' then WindowState := wsNormal else if UpperCase(Cmd) = ''''WS_MINIMIZED'''' then WindowState := wsMinimized else if UpperCase(Cmd) = ''''WS_MAXIMIZED'''' then WindowState := wsMaximized else MessageDlg(''''Invalid Command'''',mtWarning,[mbOK],0); end; end;
下面的DDE客户程序,主要是为了验证上面的DDE服务器程序而设计的,但同时也提供了一个DDE客户程序设计的完整实例。程序设计界面如图。
图7.6 DDE客户程序的设计界面
程序把接收到的DDE数据保存在一个TMemo类部件DDEDat中,而欲发送给服务器的数据和宏指令在另一个TMemo类部件PokeDat中输入。两个按钮PokeBtn、ExecuteBtn用于发送数据和宏指令。两个菜单项File|New Link和Edit|Paste Link用于根据用户的输入建立新联接和从剪贴板上粘贴DDE联接。
DDE联接的建立通过调用SetLink方法实现。
建立新联接的实现代码如下。
procedure TFormD.doNewLink(Sender: TObject); begin DDEClient.SetLink (AppName.Text, TopicName.Text); DDEClientItem.DdeConv := DDEClient; DDEClientItem.DDEItem := ItemName.Text; end;
通过从剪贴板粘贴联接信息来建立联接的实现代码如下。
procedure TFormD.Edit1Click(Sender: TObject); var Service, Topic, Item : String; begin PasteLink1.Enabled := GetPasteLinkInfo (Service, Topic, Item); end;
procedure TFormD.doPasteLink(Sender: TObject); var Service, Topic, Item : String; begin if GetPasteLinkInfo (Service, Topic, Item) then begin AppName.Text := Service; TopicName.Text := Topic; ItemName.Text := Item; DDEClient.SetLink (Service, Topic); DDEClientItem.DdeConv := DDEClient; DDEClientItem.DdeItem := ItemName.Text; end; end;
在DDEClientItem的OnChange事件处理过程中把接收到的事件保存在DDEDat中。 procedure TFormD.DDEClientItemChange(Sender: TObject); begin DDEDat.Lines := DDEClientItem.Lines; end;
数据发送的实现代码如下。 procedure TFormD.doPoke (Sender: TObject); var DDECli : TDDEClientConv; begin DDECli := DDEClientItem.DdeConv; if DdeCli <> nil then DDECli.PokeDataLines (DDEClientItem.DDEItem, PokeDat.Lines); end;
宏指令发送的实现代码如下。
procedure TFormD.doMacro (Sender: TObject); var DDECli: TDDEClientConv; Cmd: String; begin DDECli := DDEClientItem.DdeConv; if DDECli <> nil then begin Cmd := PokeDat.Text + #13#10; DDECli.ExecuteMacroLines (PokeDat.Lines, True); end; end;
运行以上两个程序,建立DDE联接。经测试,数据传输、数据发送和宏指令的发送与执行都达到预期要求。下面是两个程序同时运行后的屏幕显示。
图7.7 服务器和客户间的动态数据交换示例
7.4.4 小结
剪贴板和DDE是Windows下数据通信的两种方法。Delphi以简便、友好的方式实现了相应的功能,为用户编程提供了方便。一般说来,剪贴板多用于静态数据传输,而DDE用于动态数据交换、控制其它程序运行等场合。这些内容对上一页 [1] [2] [3] 下一页 |