国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Windows的DDE原理

2019-11-18 18:16:14
字體:
來源:轉載
供稿:網友
7.2.1 Windows的DDE原理 

Windows的DDE機制基于Windows的消息機制。兩個Windows應用程序通過相互之間傳遞DDE消息進行DDE會話(Conversation),從而完成數據的請求、應答、傳輸。這兩個應用程序分別稱為服務器(Server)和客戶(Client)。服務器是數據的提供者,客戶是數據的請求和接受者。

DDE會話由客戶程序啟動。客戶程序把一條消息(WM_DDE_INITIATE)傳播給當前運行的所有Windows程序。這條消息指明了客戶程序所需要的一般數據(應用程序、主題)。擁有這些數據的DDE服務器可以響應這條被傳播的消息。此時,DDE會話就開始了。

由于在每個主題中,DDE服務器可以支持一個或多個數據項,所以在客戶請求數據時應同時指明應用程序名、主題名和項目名。應用程序、主題、項目是DDE中三個最基本的概念。

利用Windows本身提供的DDE消息和API進行DDE編程是一件相當棘手的問題。 雖然使用DDE管理庫(ddeml.dll)可以一定程度上減輕開發者的工作負擔,但開發DDE程序仍不是一件輕松的事情。

此時Delphi出現了!Delphi通過其自身巧妙的設計使開發一個DDE應用程序同開發一個普通程序一樣地快捷、方便。


7.2.2 Delphi的DDE實現機制簡介 

Delphi把所有的DDE功能做到四個部件中,它們是:
● TDDEClientConv : 用于客戶程序建立和維護一個DDE會話
● TDDEClientItem : 用于客戶程序建立和維護數據交換通道
● TDDEServerConv : 用于服務器程序響應DDE會話
● TDDEServerItem : 用于服務器程序維護數據交換通道

  前兩個部件用于生成一個DDE客戶程序,后兩個部件用于生成一個DDE服務器程序。如果一個應用程序同時擁有這些部件,則這一程序既可以充當DDE客戶,也可以充當DDE服務器。

會話部件TDDEClientConv、TDDEServerConv用于建立和維護一個DDE會話。DDE會話包括DDE服務和DDE主題兩部分。

DDE服務是DDE服務器的名稱,即在一般的Windows DDE機制中所講的應用程序名。一般說來這一名稱是DDE服務器應用程序執行文件名去掉 .EXE后綴。比如你的應用程序要和Word 6.0建立會話,則DDE服務為WINWORD。但也不盡然。比如你的應用程序要和Borland ReportSmith ( RPTSMITH.EXE ) 建立會話,則DDE 服務為 Report Smith。DDE服務到底如何,讀者可參看相關的DDE服務器應用程序文檔。

DDE主題是一個包含了聯接信息的數據單元。一般說來DDE 主題是一個包括擴展名的完整文件名。例如和Excel中的一個文件建立DDE會話,則主題可能是 

Topic = 'c:/excel/Example/sale.xls' 

如果服務器是一個Delphi應用程序,缺省情況下主題是包含欲聯接數據窗體的標題。如果服務器使用了DDEServerConv部件,則要求使用部件DDEServerConv的名稱作為DDE主題。

項目部件TDDEclientItem、TDDEServerItem用于建立和維護DDE數據的傳輸通道。 DDE項目中包含著實際欲傳輸的數據。DDE項目的格式取決于DDE服務器應用程序。一個可能的DDE項目例子是電子表格中的單元和數據庫表中的域。如果服務器是Delphi應用程序,則項目是連接的 DDEServerItem部件的名稱。

Delphi的DDE實現機制方便、實用,但也有一個令人遺憾的缺陷:只能傳輸文本數據以及命令、宏,而不能傳輸圖像數據。在這一點上微軟公司推出的Visual Basic 要略勝一籌。不過在目前文本數據的使用仍是最廣泛的,而且圖像傳輸可以利用剪貼板和OLE來實現,則這一缺陷也并無很大的影響。 

7.3 DDE客戶程序的實現 

DDE客戶程序啟動DDE會話,向服務器請求并從服務器接收數據。同時還可以向服務器發送數據、命令、宏,改變服務器的狀態并控制服務器的運行。 

7.3.1 聯接模式(ConnectMode) 

  Delphi的DDE提供了兩種聯接模式:自動和人工。這可以通過DDEClinetConv 部件的ConnectMode屬性進行設置。如下表所示。
表 7.5 DDE的聯接模式
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
     值           意      義
───────────────────────────────
   ddeAutomatic 在運行中當包含TDDEClientConv部件的窗口創建時聯接自動建立
   ddeManual 只有當調用OpenLink方法時聯接才建立
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 

不同聯接模式,DDE客戶程序的實現方式不同。

對于自動模式:
1. 向窗體中加入DDEClientConv和DDEClientItem部件并命名;
2. 把DDEClientItem部件的DdeConv屬性設置為DDEClientConv部件的名稱;
如果在設計時建立,則通過對象觀察器進行選擇;如果在運行時建立聯系, 則通過如下的一條語句設置屬性的值:

DDEClientItem1.DdeConv := 'DDEClientConv1' ; 

3. 和服務器建立聯系,實現數據共享。

對于人工模式:

1.向窗體中加入DDEClientConv部件;
2.和服務器建立聯系;
3. 數據更新時調用RequestData方法申請并獲得數據。 

7.3.2 和DDE服務器建立聯系 

和DDE服務器建立聯系,既可以在設計時進行,也可以在運行時進行。

在設計時,DDE聯接可以通過剪貼板進行粘貼。具體步驟如下:

1. 激活服務器程序,并選中你的客戶程序欲聯接的數據;
2. 把數據和DDE聯接信息拷貝到剪貼板上。一般說來這只需要選擇服務器應用程序的 Edit|Copy 菜單;
3. 在Delphi IDE的設計窗體中選中DDEClientConv部件;
4. 在Object Inspector(對象觀察器)中單擊DDEService屬性或DDETopic屬性,然后再單擊Ellipsis按鈕,打開DDE Info對話框;
5.選擇Paste Link按鈕。此時App編輯框和Topic編輯框被自動填充。如果Paste Link按鈕變灰,說明你準備用作服務器的應用程序不支持DDE或者DDE信息沒有被成功地拷貝到剪貼板上;
6.選擇OK 按鈕。此時Object Inspector中的DDEService、DDETopic 屬性包含了建立一個DDE聯接的正確值。
對于人工模式以下步驟是不需要的。
7.選中DDEClientItem部件,并在Object Inspector中設置DdeConv屬性為已完成聯接的DDEClientConv部件名稱;
8.假如剪貼板上的DDE 聯接信息仍保留的話,從Object Inspector的下拉列表框中選擇 DDEItem 屬性的值。否則輸入正確的值。

在運行時,調用 SetLink 方法來建立DDE聯接。

SetLink有兩個String類型的參數,分別用來接受DDEService和DDETopic的值。過程執行后DDEClientConv部件的DDEService 和DDeTopic屬性被設置。要注意的是:在運行時直接設置DDEService和DDETopic的值并不能建立一個DDE聯接,而必須調用SetLink 方法進行初始化。

比如,下面的語句和Excel的System主題建立聯接: 

DDEClietnConv. SetLink('Excel','System');

調用SetLink方法后,還需要設置DDEClientItem部件的DDEItem屬性。

比如,下面的語句聯接Excel的Topics項目,用以獲取當前活躍文件的文件名:

DDEClietnItem.DDEItem := 'Topics';

當DDE聯接建立后,聯接的數據保存在DDEClientItem部件的Text和Lines 屬性中,Text用于保存一個字符串(String),Lines用于保存一個字符串鏈表(TStrings)對象。

為了顯示聯接數據,可以在DDEClientItem的OnChange事件中把數值賦給一個可視部件。

下面的事件過程把聯接數據實時地顯示在一個編輯框中。 

  PRocedure Form1.DDEClientItemChange(Sender: Tobject);
begin
Edit1.Text := DDEClientItem1.Text;
end;

運行狀態下也可以從剪貼板上粘貼DDE聯接信息,并調用SetLink建立DDE會話。下面的例子顯示了當用戶按下應用程序中的Paste Link按鈕時,動態建立DDE會話的過程。 

procedure Form1.OnPasteLink(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; 

GetPasteLinkInfo是DDEMan 庫單元中定義的一個過程。如果返回True,則DDE聯接信息保存在三個參數中;如果返回False,說明剪貼板上沒有正確格式的DDE聯接信息。 

7.3.3 數據申請 

雖然自動模式快捷、方便,但仍有一些理由使用DDE的人工模式:

1.服務器程序可能不支持自動數據傳輸,客戶必須顯式申請服務器更新一個特定的項目;
2.節省通信費用。假如沒有實時傳輸的要求,則人工模式可以大幅度降低通信的開銷;
3.若客戶程序只用于控制服務器的運行,則往往沒有必要使用自動模式。
人工模式下客戶程序的數據更新需要采用數據申請的方式。數據申請需要調用DDEClientConv部件的RequestData方法。RequestData有一個參數,指向要申請的DDE項目。RequestData返回一個Pchar類型的無結束符字符串,包含了申請到的文本。返回字符串占用的內存必須在程序終止前顯式釋放。

在人工模式下,即使存在一個DDEClientItem部件且與DDEClientConv相聯接,數據更新后DDEClientItem部件的Text、Lines屬性的值也不會改變。 

7.3.4 數據發送 

數據發送與一般的DDE數據流向正好相反,是把數據從DDE客戶應用程序發送到DDE服務器應用程序。

數據發送使用DDEClientConv部件的兩個方法PokeData 和 PokeDataLines, 它們的語法是: 

  function PokeData (Item: String ; Data: PChar): Boolean;

  function PokeDataLines (Item: String ; Data: TStrings): Boolean; 

參數Item是DDE服務器中被聯接的項目,Data是要發送的數據。如果數據是一個字符串,則把它轉化為PChar類型并調用PokeData方法;如果數據是一個字符串鏈表對象,可調用PokeDataLines方法。

方法的返回值標志數據傳送是否成功。因為有一些DDE服務器應用程序并不接收發送的數據。

下面的語句把編輯框中的內容發送給服務器: 

  StrPCopy(TheText , Edit1.text);
DDEClientConv1.PokeData(DDEClientItem1.DDEItem , TheText);
過程StrPCopy把一個Pascal類型的字符串拷貝到一個無結束符的PChar類型字符串中。
  
7.3.5 控制服務器應用程序的執行

客戶程序控制服務器應用程序的一個方面是:必要的時候客戶程序可以啟動服務器程序,并裝載會話主題。
而客戶程序控制服務器應用程序更重要的一點是向服務器發送服務器承認的宏命令,來完成對服務器應用程序的各種操作。服務器到底支持哪些宏命令,可參閱服務器應用程序文檔。

發送宏命令要使用DDEClientConv的兩個方法 ExecuteMacro和ExecuteMacroLines ,它們的語法如下:

function ExecuteMacro(Cmd: PChar; WaitFlag: Boolean): Boolean;
function ExecuteMacroLines(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中的一個工作表交換數據。程序設計界面如圖。


圖7.2 客戶程序示例設計界面 

界面中包含一個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用于記錄聯接信息。

窗口生成時進行變量和部件狀態的初始化。 

procedure TForm1.FormCreate(Sender: TObject);
begin
RequestBtn.Enabled := False;
AutoRadio.Checked := True;
Automatic := True;
end;

當聯接模式改變時,程序進行相應的處理。

自動模式轉換為人工模式:

procedure TForm1.ManualRadioClick(Sender: TObject);
begin
if Automatic then
begin
RequestBtn.Enabled := ManualRadio.Checked;
DDEClientConv1.ConnectMode := ddeManual;
Automatic := False;
end;
end;

人工模式轉換為自動模式:

procedure TForm1.AutoRadioClick(Sender: TObject);
begin
if not Automatic then
begin
RequestBtn.Enabled := ManualRadio.Checked;
If (DDEService = '') or (DDETopic = '') then
begin
MessageDlg(' Can not Set Link.',mtWarning,[mbOK],0);
Exit;
end;
DDEClientConv1.SetLink (DDEService, DDETopic);
DDEClientItem1.DdeConv := DDEClientConv1;
DDEClientItem1.DDEItem := DDEItem;
DDEClientConv1.ConnectMode := ddeAutomatic;
Automatic := True;
end;
end;

當從自動模式轉換到人工模式,只需要簡單修改相應屬性即可;而從人工模式轉換到自動模式,則需要調用SetLink重新建立聯接,否則往往會引發一個DDE異常。

聯接的建立采用從剪貼板粘貼聯接信息的方式,這是最具有靈活性的一種方法。

procedure TForm1.PasteBtnClick(Sender: TObject);
begin
if GetPasteLinkInfo (DDEService, DDETopic, DDEItem) then
begin
DDEClientConv1.SetLink (DDEService, DDETopic);
if Automatic then
begin
DDEClientItem1.DdeConv := DDEClientConv1;
DDEClientItem1.DDEItem := DDEItem;
end;
end;
end;

GetPasteInfo是 DDEMan庫單元中定義的一個函數,用于檢測剪貼板上是否有聯接信息并返回相應的DDE服務、主題和項目。

對于人工模式,必須由客戶顯式向服務器申請數據。在這種模式下DDE項目部件是多余的,接收到的DDE聯接信息用一個字符串來記錄。下面是實現代碼。 

procedure TForm1.RequestBtnClick(Sender: TObject);
var
TheData: PChar;
begin
If DDEItem = '' then
begin
MessageDlg('Can not Request Data',mtWarning,[mbOK],0);
Exit;
end;
TheData := StrAlloc(79);

DDEClientConv1.OpenLink;

TheData := DDEClientConv1.RequestData(DDEItem);

DDEClientConv1.CloseLink;

if TheData <> nil then
Memo1.Text := StrPas(TheData);
StrDisPose(TheData);
end; 

OpenLink、CloseLink方法用于打開和關閉聯接。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)DDE一個基礎的WINDOWS應用程序通訊協議,動態數據交換(DDE)為WINDOWS 應用程序相互通信提供了一個杠架,使 客戶和服務器之間開通會話,一次DDE會話(conversation)是指兩個合作應用程序從連通到結束的會話期,這兩 個應用程序必須都在運行,盡管運行前必有一定的準備。一個DDE對話必須有主題,一個最普通主題 的例子就是文件名,MICROSOFT 認為OLE大有前途,不鼓勵使用DDE,但有些事必須使用DDE來作。 

(2)現在人都在用ole, 

(3)如果數據通訊的兩方都是你自己做的,那么就不要用DDE了,好煩的,效率也不高,用WM_COPYDATA
消息要快得多,當然,如果面向工業控制,有些設備提供的就是DDE接口,那就不得不用了

上一篇:關于程序只運行一次的問題

下一篇:校驗碼輔導講座

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
學習交流
熱門圖片

新聞熱點

疑難解答

圖片精選

網友關注

主站蜘蛛池模板: 呼和浩特市| 中西区| 灵川县| 库尔勒市| 武定县| 高碑店市| 桂阳县| 枣阳市| 民乐县| 新源县| 北碚区| 虎林市| 延庆县| 富平县| 藁城市| 即墨市| 资阳市| 乌什县| 曲阳县| 博客| 宝坻区| 丹东市| 澳门| 胶州市| 甘德县| 镇宁| 惠水县| 陇川县| 神农架林区| 伽师县| 射阳县| 镇沅| 洛隆县| 财经| 遂昌县| 郸城县| 黔江区| 东阳市| 肇源县| 普定县| 枣庄市|