程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> Delphi 剪貼板和動態數據交換(3)

Delphi 剪貼板和動態數據交換(3)

編輯:Delphi

 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.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函數。 

  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.根據客戶程序發送來的宏指令改變自身的運行狀態。

  其中各部件的關鍵屬性如下: 

  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客戶程序設計的完整實例。

  程序把接收到的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.4.4 小結 

  剪貼板和DDE是Windows下數據通信的兩種方法。Delphi以簡便、友好的方式實現了相應的功能,為用戶編程提供了方便。一般說來,剪貼板多用於靜態數據傳輸,而DDE用於動態數據交換、控制其它程序運行等場合。這些內容對於多用戶環境下的程序開發是很重要的







  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved