DELPHI教程第七章.docx_第1頁
DELPHI教程第七章.docx_第2頁
DELPHI教程第七章.docx_第3頁
DELPHI教程第七章.docx_第4頁
DELPHI教程第七章.docx_第5頁
已閱讀5頁,還剩31頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第七章剪貼板和動(dòng)態(tài)數(shù)據(jù)交換(一)應(yīng)用程序間的數(shù)據(jù)交換是象Windows 這樣的多任務(wù)環(huán)境的重要特性。作為一種基于Windows的開發(fā)工具,Delphi支持如下四種數(shù)據(jù)交換方式:剪貼板、動(dòng)態(tài)數(shù)據(jù)交換 ( DDE)、對(duì)象聯(lián)接與嵌入(OLE)以及動(dòng)態(tài)聯(lián)接庫(DLLs)。這中間前三種方式最為常用,OLE功能最為強(qiáng)大,DDE次之。而剪貼板使用最為方便。在本章,我們只討論剪貼板和動(dòng)態(tài)數(shù)據(jù)交換。利用OLE實(shí)現(xiàn)數(shù)據(jù)交換見下一章,利用動(dòng)態(tài)聯(lián)接庫(DLLs)進(jìn)行數(shù)據(jù)交換將在第十章中介紹。7.1 剪貼板及其應(yīng)用本質(zhì)上,剪貼板只是一個(gè)全局內(nèi)存塊。當(dāng)一個(gè)應(yīng)用程序?qū)?shù)據(jù)傳送給剪貼板后,通過修改內(nèi)存塊分配標(biāo)志,把相關(guān)內(nèi)存塊的所有權(quán)從應(yīng)用程序移交給Windows自身。其它應(yīng)用程序可以通過一個(gè)句柄找到這個(gè)內(nèi)存塊,從而能夠從內(nèi)存塊中讀取數(shù)據(jù)。這樣就實(shí)現(xiàn)了數(shù)據(jù)在不同應(yīng)用程序間的傳輸。剪貼板雖然功能較為簡(jiǎn)單,且不能實(shí)現(xiàn)實(shí)時(shí)傳輸,但卻是更為復(fù)雜的DDE和OLE的基礎(chǔ)。對(duì)于一些只是偶爾需要使用其它應(yīng)用程序數(shù)據(jù)的程序來說,使用剪貼板不失為一種方便、快捷的方式。Delphi把剪貼板的大部分功能封裝到一個(gè)TClipboard類中,同時(shí)把使用頻度最高的文本傳輸功能(包括DBImage的圖像傳輸功能)置入相應(yīng)部件作為部件的方法,從而使用戶可以十分方便地使用剪貼板進(jìn)行編程。7.1.1 使用剪貼板傳輸文本剪貼板傳輸文本主要是應(yīng)用如下的三個(gè)方法:CopyToClipboard、CutToClipboard 和PasteFromClipboard。包含這些方法的部件如下表所示。 表7.1 包含剪貼板方法的部件方 法 部 件TDBEditTDBMemoTDBImageCopyToClipboard TEdit TMemo TMaskEditTOLEContainerTDDEServerItemTDBEdit TDBMemoCutToClipboard TDBImageTEdit TMemo TMaskEditTDBEdit TDBMemoPasteFromClipboard TDBImageTEdit TMemo TMaskEdit 除TDBImage外,其余全是有關(guān)文本的控件。在把文本傳輸?shù)郊糍N板之前,文本必須被選中。若選TMaskEdit的AutoSelect屬性為True,則當(dāng)MaskEdit獲得輸入焦點(diǎn)時(shí)文本自動(dòng)被選中;若選TEdit、TMemo的HideSelection屬性為True,則失去焦點(diǎn)時(shí),文本選中狀態(tài)自動(dòng)隱藏,重新獲得焦點(diǎn)時(shí)再顯示。下面的語句把MaskEdit中選中的文本剪切到剪貼板:MaskEdit .CutToClipboard;下面的語句把剪貼板中的文本粘貼到Memo的當(dāng)前光標(biāo)處:Memo.PasteFromClipboard;利用剪貼板類也可以實(shí)現(xiàn)文本的傳輸,見(7.1.2)中的介紹。7.1.2 剪貼板類為方便剪貼板的操作,Delphi在Clipbrd庫單元中定義了一個(gè)TClipboard類,并且預(yù)定義了一個(gè)變量Clipboard作為類TClipboard的實(shí)例,從而使用戶在絕大多數(shù)場(chǎng)合不必自己去定義一個(gè)TClipboard的實(shí)例。利用剪貼板類可以進(jìn)行文本、圖像和部件的傳輸,剪貼板類為實(shí)現(xiàn)這些方法提供了相應(yīng)的屬性和方法。表7.2、表7.3列出了TClipboard屬性和方法的意義。表 7.2 TClipboard的屬性屬 性 意 義AsText 保存剪貼板的文本,只有運(yùn)行時(shí)才可設(shè)置FormatCount 可用剪貼板格式的數(shù)目Formats 可用剪貼板格式鏈 表 7.3 TClipboard的方法方 法 參 數(shù) 意 義Clear 無 清除剪貼板的內(nèi)容Assign Source:TPersistent 把Source參數(shù)指定的對(duì)象拷貝到剪貼板,常用于圖形、圖像對(duì)象Open 無打開剪貼板,阻止其它應(yīng)用程序改變它的內(nèi)容Close 無 關(guān)閉打開的剪貼板SetComponent Source:TPersistent 把部件拷貝到剪貼板GetComponent Owner 從剪貼板取回一個(gè)部件并放置Parent :TPersistentSetAsHandle Format:Word 把指定格式數(shù)據(jù)的句柄交給剪貼板返回類型:THandleGetAsHandle Format:Word 返回剪貼板指定格式數(shù)據(jù)的句柄返回類型:THandleHasFormat Format:Word 判斷剪貼板是否擁有給定的格式返回類型:BooleanSetTextBuf Buffer:PChar 設(shè)置剪貼板的文本內(nèi)容剪貼板中可能的數(shù)據(jù)格式如下表。表 7.4剪貼板數(shù)據(jù)格式及其意義數(shù)據(jù)格式 意 義CF_TEXT 文本。每行以CF_LF結(jié)束,nil標(biāo)志文本結(jié)束CF_BITMAP Windows位圖CF_METAFILE Windows元文件 CF_PICTURE TPicture類型的對(duì)象CF_OBJECT 任何TPersistent類型的對(duì)象利用TClipboard實(shí)現(xiàn)文本的傳輸使用AsText屬性和SetTextBuf方法。AsText屬性為非控件部件的剪貼板操作提供了方便。如:Clipboard. AsText := Form1.Caption ;把Form1的標(biāo)題拷貝到剪貼板。Label1.Caption := Clipboard.AsText;把剪貼板中的文本寫入Label1。SetTextBuf用于把超過255個(gè)字符的字符串拷入剪貼板。7.1.3 利用剪貼板傳輸圖像7.1.3.1 拷貝Image部件上的內(nèi)容和窗體上的圖形可以直接拷貝到剪貼板。圖像拷貝利用Clipboard的Assign方法。例如:Clipboard.Assign(Image1.Picture);把Image1上的圖像拷貝到剪貼板。7.1.3.2 剪切圖像的剪切是首先把圖像拷貝到剪貼板,而后在原位置用空白圖像進(jìn)行覆蓋。下面一段程序表示了圖像的剪切。 procedure TForm1.Cut1Click(Sender: TObject);varARect: TRect;beginClipboard.Assign(Image1.Picture);with Image.Canvas dobeginCopyMode := cmWhiteness; ARect := Rect(0, 0, Image.Width, Image.Height); CopyRect(ARect, Image.Canvas, ARect); CopyMode := cmSrcCopy; end;end;7.1.3.3 粘貼從剪貼板上粘貼圖像,首先檢測(cè)剪貼板上的數(shù)據(jù)格式。如果格式為CF_BITMAP,則調(diào)用目標(biāo)位圖的Assign 方法粘貼圖像。程序清單如下。procedure TForm1.PasteButtonClick(Sender: TObject);varBitmap: TBitmap;beginif Clipboard.HasFormat(CF_BITMAP) then beginBitmap := TBitmap.Create; tryBitmap.Assign(Clipboard); Image.Canvas.Draw(0, 0, Bitmap); finallyBitmap.Free;end;end;end;try.finally為資源保護(hù)塊,參第十二章。7.1.4 建立自己的剪貼板觀察程序在這一節(jié)中我們要建立一個(gè)自己的剪貼板觀察程序,用來保存截獲到剪貼板中的位圖。Windows允許用戶建立自己的剪貼板觀察程序,并把該程序添加到一個(gè)剪貼板觀察器鏈中。在鏈中,位置靠前的程序有義務(wù)把有關(guān)剪貼板的消息傳遞到緊隨其后的觀察程序。而處于鏈?zhǔn)椎某绦蛴蒞indows的消息循環(huán)機(jī)制直接把剪貼板消息發(fā)送過來。建立一個(gè)剪貼板觀察程序,首先該程序必須能響應(yīng)相應(yīng)的Windows消息。對(duì)于那些熟悉Microsoft公司Visual Basic的讀者來說,這是令他們頭疼而束手無策的地方。但Delphi在這方面卻有良好的表現(xiàn):利用關(guān)鍵字message,用戶可以將一個(gè)過程定義為響應(yīng)特定的Windows消息。如:procedure WMDrawClipboard(var Msg:TWMDrawClipboard);message WM_DRAWCLIPBOARD;可以響應(yīng)WM_DRAWCLIPBOARD消息。類TWMDrawClipboard是消息類Message 的子類。Delphi把所有的消息都重新進(jìn)行了定義,使用戶在使用時(shí)可以直接引用其便于記憶的數(shù)據(jù)成員,而不必再自己動(dòng)手去分解消息。雖然這并不能算作是一個(gè)重大的改進(jìn),但卻體現(xiàn)了Delphi處處為用戶方便著想的特點(diǎn)。我們將要建立的程序目的是把截獲到剪貼板上的位圖保存下來。在本書的寫作過程中,這一工作是大量存在的。雖然利用Windows工具PaintBrush(畫筆),通過粘貼、保存等操作可以實(shí)現(xiàn)這一功能,但卻存在以下一些問題:1.程序頻繁切換影響效率,當(dāng)有大量位圖存在時(shí)更是如此;2.畫筆有一個(gè)很討厭的缺陷:當(dāng)剪貼板上的位圖比畫筆界面的客戶區(qū)大時(shí),客戶區(qū)外的位圖被截?cái)?。因而往往需要根?jù)所截獲位圖的大小來調(diào)整畫筆客戶區(qū)的大小,并重新進(jìn)行粘貼。而如果開始就把畫筆客戶區(qū)調(diào)整到足夠大,又會(huì)覆蓋掉屏幕上一些有用的信息。為解決這些問題,我開發(fā)了下面的程序。程序啟動(dòng)時(shí),以極小化方式運(yùn)行。此時(shí)只要剪貼板中存入位圖,則自動(dòng)彈出一個(gè)對(duì)話框請(qǐng)求用戶保存。如果用戶希望查看確認(rèn),則可以雙擊運(yùn)行程序圖標(biāo),選擇相應(yīng)按鈕,剪貼板中的位圖就會(huì)顯示在屏幕上。部件關(guān)鍵屬性設(shè)計(jì)如下:ClipSaveForm:CaptionSave Bitmap in Clipboard Panel1:Align = Top Image1:Align = Client SaveDialog1:FileEditStyle = fsEditFileName = *.bmpFilter = Bitmap Files(*.bmp)|*.bmp|Any Files(*.*)|*.*InitialDir = c:bmpTitle = Save Bitmap程序主窗口是TForm派生類TClipSaveForm的實(shí)例。TClipSaveForm通過定義一些私有數(shù)據(jù)成員和過程,使響應(yīng)和處理Windows的相應(yīng)消息成為可能。下面是TClipSaveForm的類定義:typeTClipSaveForm = class(TForm)SaveDialog1: TSaveDialog;Image1: TImage;Panel1: TPanel;Button1: TButton;SpeedButton1: TSpeedButton;SpeedButton2: TSpeedButton;Button2: TButton;procedure FormCreate(Sender: TObject);procedure FormDestroy(Sender: TObject);procedure Button1Click(Sender: TObject);procedure Button2Click(Sender: TObject);procedure SpeedButton1Click(Sender: TObject);procedure SpeedButton2Click(Sender: TObject);private Private declarations MyBitmap: TBitmap; 保存截獲的位圖 View: Boolean; 判斷是否顯示 NextViewerHandle: HWND; 下一剪貼板觀察器的句柄 procedure WMDrawClipboard(var Msg:TWMDrawClipboard);message WM_DRAWCLIPBOARD;procedure WMChangeCBChain(var Msg:TWMChangeCBChain);message WM_CHANGECBCHAIN; 響應(yīng)Windows的剪貼板消息 public Public declarations end;窗口創(chuàng)建時(shí),把該窗口登錄為剪貼板觀察器,添加到剪貼板觀察器鏈中,同時(shí)進(jìn)行變量、部件和剪貼板的初始化。procedure TClipSaveForm.FormCreate(Sender: TObject);beginView := False;SpeedButton2.Down := True;MyBitmap := TBitmap.create;tryMyBitmap.Width := 0;MyBitmap.Height := 0 ;exceptApplication.terminate;end;Clipboard.Clear;NextViewerHandle := SetClipboardViewer(Handle);end;窗口關(guān)閉時(shí),退出剪貼板觀察器鏈,并釋放內(nèi)存:procedure TClipSaveForm.FormDestroy(Sender: TObject);beginChangeClipboardChain(Handle,NextViewerHandle);MyBitmap.Free;end;在以上兩段程序中用到的兩個(gè)Windows API函數(shù)SetClipboardViewer和ChangeClipboardChain分別用于登錄和退出剪貼板觀察器鏈。程序保存位圖的功能是在消息響應(yīng)過程WMDrawClipboard中實(shí)現(xiàn)的。該過程在剪貼板內(nèi)容有變化時(shí)被調(diào)用。procedure TClipSaveForm.WMDrawClipboard(var Msg: TWMDrawClipboard);varFileName: String;beginIf NextViewerHandle 0 thenSendMessage(NextViewerHandle,msg.Msg,0,0);If ClipBoard.HasFormat(CF_BITMAP) thenbeginMyBitmap.Assign(Clipboard);If SaveDialog1.Execute thenbeginFileName := SaveDialog1.FileName;MyBitmap.SaveToFile(FileName);end;If View thenbeginWindowState := wsNormal;Image1.Picture.Bitmap := MyBitmap;end;end;Msg.Result := 0;end;程序首先判斷在剪貼板觀察器鏈中是否還存在下一個(gè)觀察器。如果有,則把消息傳遞下去,這是剪貼板觀察器程序的義務(wù)。而后判斷剪貼板上內(nèi)容的格式是否為位圖。如是,則首先把剪貼板上內(nèi)容保存到數(shù)據(jù)成員MyBitmap中,并激活一個(gè)文件保存對(duì)話框把位圖保存到文件中。如果View=True,則把窗口狀態(tài)(WindowState)設(shè)置為wsNormal,并把MyBitmap賦給Image部件的相應(yīng)值,使用戶可以對(duì)剪貼板上的位圖進(jìn)行觀察。消息響應(yīng)過程WMChangeCBChain在剪貼板觀察器鏈上其它觀察器退出時(shí)被調(diào)用。根據(jù)被移出觀察器的不同位置決定了不同的處理方法。procedure TClipSaveForm.WMChangeCBChain(var Msg: TWMChangeCBChain);beginif Msg.Remove = NextViewerHandle thenNextViewerHandle := Msg.Nextelseif NextViewerHandle 0 thenSendMessage(NextViewerHandle,Msg.Msg,Msg.Remove,Msg.Next);Msg.Result := 0;end;窗口上有兩個(gè)加速按鈕,兩個(gè)按鈕。它們擊鍵(click)事件處理過程如下。每一程序段的意義是非常顯然的。procedure TClipSaveForm.Button1Click(Sender: TObject);beginClose;end;procedure TClipSaveForm.Button2Click(Sender: TObject);beginWindowState := wsMinimized;end;procedure TClipSaveForm.SpeedButton1Click(Sender: TObject);beginView := True;Image1.Picture.Bitmap := MyBitmap;end;procedure TClipSaveForm.SpeedButton2Click(Sender: TObject);beginView := False;Image1.Picture.Bitmap := nil;end;通過對(duì)這個(gè)程序的介紹,以下幾點(diǎn)是應(yīng)該注意的:1.提供了一種自己截獲和處理剪貼板上內(nèi)容的方法。讀者可以根據(jù)需要進(jìn)一步擴(kuò)充;2.提供了響應(yīng)Windows消息的方法。在第三篇有關(guān)自定義部件開發(fā)的內(nèi)容中,這一問題還要詳細(xì)論述;3.最后的一點(diǎn)啟示是:在Delphi程序開發(fā)中巧妙應(yīng)用傳統(tǒng)的Windows方法(如消息處理、 API函數(shù)等)仍是很有必要的。而在應(yīng)用這些方法中所體現(xiàn)的方便之處,正是Delphi勝過其它可視化開發(fā)工具的一個(gè)重要方面。7.2 Windows的DDE原理和 Dephi的DDE實(shí)現(xiàn)機(jī)制7.2.1 Windows的DDE原理Windows的DDE機(jī)制基于Windows的消息機(jī)制。兩個(gè)Windows應(yīng)用程序通過相互之間傳遞DDE消息進(jìn)行DDE會(huì)話(Conversation),從而完成數(shù)據(jù)的請(qǐng)求、應(yīng)答、傳輸。這兩個(gè)應(yīng)用程序分別稱為服務(wù)器(Server)和客戶(Client)。服務(wù)器是數(shù)據(jù)的提供者,客戶是數(shù)據(jù)的請(qǐng)求和接受者。DDE會(huì)話由客戶程序啟動(dòng)。客戶程序把一條消息(WM_DDE_INITIATE)傳播給當(dāng)前運(yùn)行的所有Windows程序。這條消息指明了客戶程序所需要的一般數(shù)據(jù)(應(yīng)用程序、主題)。擁有這些數(shù)據(jù)的DDE服務(wù)器可以響應(yīng)這條被傳播的消息。此時(shí),DDE會(huì)話就開始了。由于在每個(gè)主題中,DDE服務(wù)器可以支持一個(gè)或多個(gè)數(shù)據(jù)項(xiàng),所以在客戶請(qǐng)求數(shù)據(jù)時(shí)應(yīng)同時(shí)指明應(yīng)用程序名、主題名和項(xiàng)目名。應(yīng)用程序、主題、項(xiàng)目是DDE中三個(gè)最基本的概念。利用Windows本身提供的DDE消息和API進(jìn)行DDE編程是一件相當(dāng)棘手的問題。 雖然使用DDE管理庫(ddeml.dll)可以一定程度上減輕開發(fā)者的工作負(fù)擔(dān),但開發(fā)DDE程序仍不是一件輕松的事情。此時(shí)Delphi出現(xiàn)了!Delphi通過其自身巧妙的設(shè)計(jì)使開發(fā)一個(gè)DDE應(yīng)用程序同開發(fā)一個(gè)普通程序一樣地快捷、方便。7.2.2 Delphi的DDE實(shí)現(xiàn)機(jī)制簡(jiǎn)介Delphi把所有的DDE功能做到四個(gè)部件中,它們是: TDDEClientConv : 用于客戶程序建立和維護(hù)一個(gè)DDE會(huì)話 TDDEClientItem : 用于客戶程序建立和維護(hù)數(shù)據(jù)交換通道 TDDEServerConv : 用于服務(wù)器程序響應(yīng)DDE會(huì)話 TDDEServerItem : 用于服務(wù)器程序維護(hù)數(shù)據(jù)交換通道 前兩個(gè)部件用于生成一個(gè)DDE客戶程序,后兩個(gè)部件用于生成一個(gè)DDE服務(wù)器程序。如果一個(gè)應(yīng)用程序同時(shí)擁有這些部件,則這一程序既可以充當(dāng)DDE客戶,也可以充當(dāng)DDE服務(wù)器。會(huì)話部件TDDEClientConv、TDDEServerConv用于建立和維護(hù)一個(gè)DDE會(huì)話。DDE會(huì)話包括DDE服務(wù)和DDE主題兩部分。DDE服務(wù)是DDE服務(wù)器的名稱,即在一般的Windows DDE機(jī)制中所講的應(yīng)用程序名。一般說來這一名稱是DDE服務(wù)器應(yīng)用程序執(zhí)行文件名去掉 .EXE后綴。比如你的應(yīng)用程序要和Word 6.0建立會(huì)話,則DDE服務(wù)為WINWORD。但也不盡然。比如你的應(yīng)用程序要和Borland ReportSmith ( RPTSMITH.EXE ) 建立會(huì)話,則DDE 服務(wù)為 Report Smith。DDE服務(wù)到底如何,讀者可參看相關(guān)的DDE服務(wù)器應(yīng)用程序文檔。DDE主題是一個(gè)包含了聯(lián)接信息的數(shù)據(jù)單元。一般說來DDE 主題是一個(gè)包括擴(kuò)展名的完整文件名。例如和Excel中的一個(gè)文件建立DDE會(huì)話,則主題可能是Topic = c:excelExamplesale.xls如果服務(wù)器是一個(gè)Delphi應(yīng)用程序,缺省情況下主題是包含欲聯(lián)接數(shù)據(jù)窗體的標(biāo)題。如果服務(wù)器使用了DDEServerConv部件,則要求使用部件DDEServerConv的名稱作為DDE主題。項(xiàng)目部件TDDEclientItem、TDDEServerItem用于建立和維護(hù)DDE數(shù)據(jù)的傳輸通道。 DDE項(xiàng)目中包含著實(shí)際欲傳輸?shù)臄?shù)據(jù)。DDE項(xiàng)目的格式取決于DDE服務(wù)器應(yīng)用程序。一個(gè)可能的DDE項(xiàng)目例子是電子表格中的單元和數(shù)據(jù)庫表中的域。如果服務(wù)器是Delphi應(yīng)用程序,則項(xiàng)目是連接的 DDEServerItem部件的名稱。Delphi的DDE實(shí)現(xiàn)機(jī)制方便、實(shí)用,但也有一個(gè)令人遺憾的缺陷:只能傳輸文本數(shù)據(jù)以及命令、宏,而不能傳輸圖像數(shù)據(jù)。在這一點(diǎn)上微軟公司推出的Visual Basic 要略勝一籌。不過在目前文本數(shù)據(jù)的使用仍是最廣泛的,而且圖像傳輸可以利用剪貼板和OLE來實(shí)現(xiàn),則這一缺陷也并無很大的影響7.3 DDE客戶程序的實(shí)現(xiàn)DDE客戶程序啟動(dòng)DDE會(huì)話,向服務(wù)器請(qǐng)求并從服務(wù)器接收數(shù)據(jù)。同時(shí)還可以向服務(wù)器發(fā)送數(shù)據(jù)、命令、宏,改變服務(wù)器的狀態(tài)并控制服務(wù)器的運(yùn)行。7.3.1 聯(lián)接模式(ConnectMode)Delphi的DDE提供了兩種聯(lián)接模式:自動(dòng)和人工。這可以通過DDEClinetConv 部件的ConnectMode屬性進(jìn)行設(shè)置。如下表所示。表 7.5 DDE的聯(lián)接模式值意義ddeAutomatic 在運(yùn)行中當(dāng)包含TDDEClientConv部件的窗口創(chuàng)建時(shí)聯(lián)接自動(dòng)建立 ddeManual 只有當(dāng)調(diào)用OpenLink方法時(shí)聯(lián)接才建立不同聯(lián)接模式,DDE客戶程序的實(shí)現(xiàn)方式不同。對(duì)于自動(dòng)模式:1. 向窗體中加入DDEClientConv和DDEClientItem部件并命名;2. 把DDEClientItem部件的DdeConv屬性設(shè)置為DDEClientConv部件的名稱;如果在設(shè)計(jì)時(shí)建立,則通過對(duì)象觀察器進(jìn)行選擇;如果在運(yùn)行時(shí)建立聯(lián)系, 則通過如下的一條語句設(shè)置屬性的值:DDEClientItem1.DdeConv := DDEClientConv1 ;3. 和服務(wù)器建立聯(lián)系,實(shí)現(xiàn)數(shù)據(jù)共享。對(duì)于人工模式:1.向窗體中加入DDEClientConv部件;2.和服務(wù)器建立聯(lián)系;3. 數(shù)據(jù)更新時(shí)調(diào)用RequestData方法申請(qǐng)并獲得數(shù)據(jù)。7.3.2 和DDE服務(wù)器建立聯(lián)系和DDE服務(wù)器建立聯(lián)系,既可以在設(shè)計(jì)時(shí)進(jìn)行,也可以在運(yùn)行時(shí)進(jìn)行。在設(shè)計(jì)時(shí),DDE聯(lián)接可以通過剪貼板進(jìn)行粘貼。具體步驟如下:1. 激活服務(wù)器程序,并選中你的客戶程序欲聯(lián)接的數(shù)據(jù);2. 把數(shù)據(jù)和DDE聯(lián)接信息拷貝到剪貼板上。一般說來這只需要選擇服務(wù)器應(yīng)用程序的 Edit|Copy 菜單;3. 在Delphi IDE的設(shè)計(jì)窗體中選中DDEClientConv部件;4. 在Object Inspector(對(duì)象觀察器)中單擊DDEService屬性或DDETopic屬性,然后再單擊Ellipsis按鈕,打開DDE Info對(duì)話框;5.選擇Paste Link按鈕。此時(shí)App編輯框和Topic編輯框被自動(dòng)填充。如果Paste Link按鈕變灰,說明你準(zhǔn)備用作服務(wù)器的應(yīng)用程序不支持DDE或者DDE信息沒有被成功地拷貝到剪貼板上;6.選擇OK 按鈕。此時(shí)Object Inspector中的DDEService、DDETopic 屬性包含了建立一個(gè)DDE聯(lián)接的正確值。對(duì)于人工模式以下步驟是不需要的。7.選中DDEClientItem部件,并在Object Inspector中設(shè)置DdeConv屬性為已完成聯(lián)接的DDEClientConv部件名稱;8.假如剪貼板上的DDE 聯(lián)接信息仍保留的話,從Object Inspector的下拉列表框中選擇 DDEItem 屬性的值。否則輸入正確的值。在運(yùn)行時(shí),調(diào)用 SetLink 方法來建立DDE聯(lián)接。SetLink有兩個(gè)String類型的參數(shù),分別用來接受DDEService和DDETopic的值。過程執(zhí)行后DDEClientConv部件的DDEService 和DDeTopic屬性被設(shè)置。要注意的是:在運(yùn)行時(shí)直接設(shè)置DDEService和DDETopic的值并不能建立一個(gè)DDE聯(lián)接,而必須調(diào)用SetLink 方法進(jìn)行初始化。比如,下面的語句和Excel的System主題建立聯(lián)接:DDEClietnConv. SetLink(Excel,System);調(diào)用SetLink方法后,還需要設(shè)置DDEClientItem部件的DDEItem屬性。比如,下面的語句聯(lián)接Excel的Topics項(xiàng)目,用以獲取當(dāng)前活躍文件的文件名:DDEClietnItem.DDEItem := Topics;當(dāng)DDE聯(lián)接建立后,聯(lián)接的數(shù)據(jù)保存在DDEClientItem部件的Text和Lines 屬性中,Text用于保存一個(gè)字符串(String),Lines用于保存一個(gè)字符串鏈表(TStrings)對(duì)象。為了顯示聯(lián)接數(shù)據(jù),可以在DDEClientItem的OnChange事件中把數(shù)值賦給一個(gè)可視部件。下面的事件過程把聯(lián)接數(shù)據(jù)實(shí)時(shí)地顯示在一個(gè)編輯框中。 procedure Form1.DDEClientItemChange(Sender: Tobject);beginEdit1.Text := DDEClientItem1.Text;end;運(yùn)行狀態(tài)下也可以從剪貼板上粘貼DDE聯(lián)接信息,并調(diào)用SetLink建立DDE會(huì)話。下面的例子顯示了當(dāng)用戶按下應(yīng)用程序中的Paste Link按鈕時(shí),動(dòng)態(tài)建立DDE會(huì)話的過程。procedure Form1.OnPasteLink(Sender: Tobject);varService, Topic, Item: String;beginif GetPasteLinkInfo (Service, Topic, Item) thenbeginAppName.Text := Service;TopicName.Text := Topic;ItemName.Text := Item;DDEClient.SetLink (Service, Topic); DDEClientItem.DdeConv := DDEClient;DDEClientItem.DDEItem := ItemName.Text;end;end;GetPasteLinkInfo是DDEMan 庫單元中定義的一個(gè)過程。如果返回True,則DDE聯(lián)接信息保存在三個(gè)參數(shù)中;如果返回False,說明剪貼板上沒有正確格式的DDE聯(lián)接信息。7.3.3 數(shù)據(jù)申請(qǐng)雖然自動(dòng)模式快捷、方便,但仍有一些理由使用DDE的人工模式:1.服務(wù)器程序可能不支持自動(dòng)數(shù)據(jù)傳輸,客戶必須顯式申請(qǐng)服務(wù)器更新一個(gè)特定的項(xiàng)目;2.節(jié)省通信費(fèi)用。假如沒有實(shí)時(shí)傳輸?shù)囊螅瑒t人工模式可以大幅度降低通信的開銷;3.若客戶程序只用于控制服務(wù)器的運(yùn)行,則往往沒有必要使用自動(dòng)模式。人工模式下客戶程序的數(shù)據(jù)更新需要采用數(shù)據(jù)申請(qǐng)的方式。數(shù)據(jù)申請(qǐng)需要調(diào)用DDEClientConv部件的RequestData方法。RequestData有一個(gè)參數(shù),指向要申請(qǐng)的DDE項(xiàng)目。RequestData返回一個(gè)Pchar類型的無結(jié)束符字符串,包含了申請(qǐng)到的文本。返回字符串占用的內(nèi)存必須在程序終止前顯式釋放。在人工模式下,即使存在一個(gè)DDEClientItem部件且與DDEClientConv相聯(lián)接,數(shù)據(jù)更新后DDEClientItem部件的Text、Lines屬性的值也不會(huì)改變。7.3.4 數(shù)據(jù)發(fā)送數(shù)據(jù)發(fā)送與一般的DDE數(shù)據(jù)流向正好相反,是把數(shù)據(jù)從DDE客戶應(yīng)用程序發(fā)送到DDE服務(wù)器應(yīng)用程序。數(shù)據(jù)發(fā)送使用DDEClientConv部件的兩個(gè)方法PokeData 和 PokeDataLines, 它們的語法是:function PokeData (Item: String ; Data: PChar): Boolean;function PokeDataLines (Item: String ; Data: TStrings): Boolean;參數(shù)Item是DDE服務(wù)器中被聯(lián)接的項(xiàng)目,Data是要發(fā)送的數(shù)據(jù)。如果數(shù)據(jù)是一個(gè)字符串,則把它轉(zhuǎn)化為PChar類型并調(diào)用PokeData方法;如果數(shù)據(jù)是一個(gè)字符串鏈表對(duì)象,可調(diào)用PokeDataLines方法。 方法的返回值標(biāo)志數(shù)據(jù)傳送是否成功。因?yàn)橛幸恍〥DE服務(wù)器應(yīng)用程序并不接收發(fā)送的數(shù)據(jù)。下面的語句把編輯框中的內(nèi)容發(fā)送給服務(wù)器:StrPCopy(TheText , Edit1.text);DDEClientConv1.PokeData(DDEClientItem1.DDEItem , TheText);過程StrPCopy把一個(gè)Pascal類型的字符串拷貝到一個(gè)無結(jié)束符的PChar類型字符串中。第七章剪貼板和動(dòng)態(tài)數(shù)據(jù)交換(二)7.3.5 控制服務(wù)器應(yīng)用程序的執(zhí)行客戶程序控制服務(wù)器應(yīng)用程序的一個(gè)方面是:必要的時(shí)候客戶程序可以啟動(dòng)服務(wù)器程序,并裝載會(huì)話主題。而客戶程序控制服務(wù)器應(yīng)用程序更重要的一點(diǎn)是向服務(wù)器發(fā)送服務(wù)器承認(rèn)的宏命令,來完成對(duì)服務(wù)器應(yīng)用程序的各種操作。服務(wù)器到底支持哪些宏命令,可參閱服務(wù)器應(yīng)用程序文檔。發(fā)送宏命令要使用DDEClientConv的兩個(gè)方法 ExecuteMacro和ExecuteMacroLines ,它們的語法如下:function ExecuteMacro(Cmd: PChar; WaitFlag: Boolean): Boolean;function ExecuteMacroLines(Cmd: TStrings;WaitFlag: Boolean): Boolean;Cmd是欲發(fā)送的宏命令字符串或宏命令字符串鏈表。WaitFlag決定了在DDE 服務(wù)器程序執(zhí)行宏命令時(shí)客戶程序的行為。如果WaitFlag設(shè)置為True,則在服務(wù)器宏命令執(zhí)行完畢前,不允許對(duì)ExecuteMacro、ExecuteMacroLines、PokeData、PokeDataLines這些方法的成功調(diào)用,它們都不向服務(wù)器發(fā)送數(shù)據(jù)并返回False。如果WaitFlag設(shè)置為False,則調(diào)用的方法在第一個(gè)宏執(zhí)行完畢前即試圖向服務(wù)器發(fā)送數(shù)據(jù)。WaitFalg的設(shè)置也取決于服務(wù)器應(yīng)用程序。一些應(yīng)用程序當(dāng)在第一個(gè)宏執(zhí)行完之前就試圖向它發(fā)送數(shù)據(jù)或命令時(shí),可能導(dǎo)致第一個(gè)宏執(zhí)行失敗或?qū)е虏豢深A(yù)料的后果。具體情況可查閱服務(wù)器應(yīng)用程序文檔。函數(shù)返回值表示命令串是否被成功傳輸。而宏命令執(zhí)行是否成功客戶是無法檢測(cè)到的。7.3.6 格式化文本DDEClientConv有一個(gè)布爾屬性FormartChars,用于決定是否格式化文本。所謂格式化文本是指從傳輸來的文本數(shù)據(jù)中過濾掉BackSpace(8)、 Tab(7) 、Linefeed(10) 、Return(13)等字符。括號(hào)內(nèi)是字符的ASCII碼。許多時(shí)候這些字符將導(dǎo)致DDE客戶數(shù)據(jù)顯示的混亂。FormatChars的缺省值是False。7.3.7 響應(yīng)DDE事件部件DDEClientConv有兩個(gè)事件OnOpen和OnClose,分別在DDE 會(huì)話建立和中止時(shí)觸發(fā)。部件DDEClientItem有一個(gè)OnChange事件。這一事件常用于DDE項(xiàng)目數(shù)據(jù)的轉(zhuǎn)儲(chǔ)和顯示,如(7.3.1)節(jié)所示。在自動(dòng)模式下,OnOpen事件在包含DDEClientConv部件的窗口創(chuàng)建時(shí)觸發(fā),或在調(diào)用SetLink方法時(shí)觸發(fā),OnClose事件在客戶程序或服務(wù)器程序關(guān)閉時(shí)觸發(fā)。在人工模式下,OnOpen事件在調(diào)用OpenLink 方法時(shí)觸發(fā),OnClose事件在調(diào)用ColseLink方法時(shí)觸發(fā)。7.3.8 利用客戶程序和Excel交換數(shù)據(jù)下面我們建立一個(gè)DDE客戶程序,并利用這一程序與Excel中的一個(gè)工作表交換數(shù)據(jù)。程序設(shè)計(jì)界面界面中包含一個(gè)DDE會(huì)話部件DDEClientConv1和DDE項(xiàng)目部件DDEClientItem1,用于建立和維護(hù)DDE聯(lián)接;一個(gè)RadioGroup控件和其中的兩個(gè)無線電按鈕AutoRadio、ManualRadio,用于設(shè)置聯(lián)接模式;一個(gè)GroupBox控件和其中的兩個(gè)按鈕RequestBtn和PokeBtn,用于控制數(shù)據(jù)的申請(qǐng)和發(fā)送,其中RequestBtn在自動(dòng)模式下變灰;一個(gè)文本框Memo1用于保存DDE數(shù)據(jù);一個(gè)按鈕PasteBtn用于粘貼聯(lián)接信息并建立DDE聯(lián)接;另外一個(gè)按鈕CloseBtn用于關(guān)閉系統(tǒng)。設(shè)計(jì)時(shí)把DDEClientConv1的FormatChars屬性置為True,這樣可以保留服務(wù)器傳來數(shù)據(jù)的顯示格式;ConnectMode保留ddeAutomatic的缺省設(shè)置。程序在類TForm1中定義了一個(gè)私有數(shù)據(jù)成員Automatic,用于標(biāo)志聯(lián)接模式;三個(gè)字符串?dāng)?shù)據(jù)成員DDEService、DDETopic、DDEItem用于記錄聯(lián)接信息。窗口生成時(shí)進(jìn)行變量和部件狀態(tài)的初始化。procedure TForm1.FormCreate(Sender: TObject);beginRequestBtn.Enabled := False;AutoRadio.Checked := True;Automatic := True;end;當(dāng)聯(lián)接模式改變時(shí),程序進(jìn)行相應(yīng)的處理。自動(dòng)模式轉(zhuǎn)換為人工模式:procedure TForm1.ManualRadioClick(Sender: TObject);beginif Automatic thenbeginRequestBtn.Enabled := ManualRadio.Checked;DDEClientConv1.ConnectMode := ddeManual;Automatic := False;end;end;人工模式轉(zhuǎn)換為自動(dòng)模式:procedure TForm1.AutoRadioClick(Sender: TObject);beginif not Automatic thenbeginRequestBtn.Enabled := ManualRadio.Checked;If (DDEService = ) or (DDETopic = ) thenbeginMessageDlg( 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;當(dāng)從自動(dòng)模式轉(zhuǎn)換到人工模式,只需要簡(jiǎn)單修改相應(yīng)屬性即可;而從人工模式轉(zhuǎn)換到自動(dòng)模式,則需要調(diào)用SetLink重新建立聯(lián)接,否則往往會(huì)引發(fā)一個(gè)DDE異常。聯(lián)接的建立采用從剪貼板粘貼聯(lián)接信息的方式,這是最具有靈活性的一種方法。procedure TForm1.PasteBtnClick(Sender: TObject);beginif GetPasteLinkInfo (DDEService, DDETopic, DDEItem) thenbeginDDEClientConv1.SetLink (DDEService, DDETopic);if Automatic thenbeginDDEClientItem1.DdeConv := DDEClientConv1;DDEClientItem1.DDEItem := DDEItem;end;end;end;GetPasteInfo是 DDEMan庫單元中定義的一個(gè)函數(shù),用于檢測(cè)剪貼板上是否有聯(lián)接信息并返回相應(yīng)的DDE服務(wù)、主題和項(xiàng)目。對(duì)于人工模式,必須由客戶顯式向服務(wù)器申請(qǐng)數(shù)據(jù)。在這種模式下DDE項(xiàng)目部件是多余的,接收到的DDE聯(lián)接信息用一個(gè)字符串來記錄。下面是實(shí)現(xiàn)代碼。procedure TForm1.RequestBtnClick(Sender: TObject);varTheData: PChar;beginIf DDEItem = thenbeginMessageDlg(Can not Request Data,mtWarning,mbOK,0);Exit;end;TheData := StrAlloc(79);DDEClientConv1.OpenLink;TheData := DDEClientConv1.RequestData(DDEItem);DDEClientConv1.CloseLink;if TheData nil thenMemo1.Text := StrPas(TheData);StrDisPose(TheData);end;OpenLink、CloseLink方法用于打開和關(guān)閉聯(lián)接。RequestData方法向服務(wù)器申請(qǐng)數(shù)據(jù)并返回到一個(gè)PChar字符串中。字符串必須顯式分配內(nèi)存并在退出時(shí)釋放。數(shù)據(jù)發(fā)送在不同聯(lián)接模式下是不同的。對(duì)于人工模式,增加了聯(lián)接的打開和關(guān)閉操作。程序清單如下。procedure TForm1.PokeBtnClick(Sender: TObject);beginIf DDEItem = thenbeginMessageDlg(Can not Poke Data.,mtWarning,mbOK,0);Exit;end;if Automatic thenDDEClientConv1.PokeDataLines(DDEItem,Memo1.Lines)elsebeginDDEClientConv1.OpenLink;DDEClientConv1.PokeDataLines(DDEItem,Memo1.Lines);DDEClientConv1.CloseLink;end;end;打開Microsoft Office中的Excel,裝入一個(gè)文件,把相關(guān)的單元選中,拷貝到剪貼板上。而后運(yùn)行程序,按下Paste Link按鈕,DDE聯(lián)接就建立起來,相關(guān)單元中的數(shù)據(jù)顯示在Memo1中。之后可以進(jìn)行模式轉(zhuǎn)換、數(shù)據(jù)申請(qǐng)、申請(qǐng)發(fā)送等一系列工作。運(yùn)行后的屏幕顯示如下圖所示。7.3.9 用客戶程序控制程序管理器下面的例子用客戶程序向程序管理器發(fā)送命令,用于創(chuàng)建程序組、程序項(xiàng)以及刪除程序組。 程序管理器提供了應(yīng)用程序的DDE接口命令字符串,應(yīng)用程序利用這些命令字符串可以實(shí)現(xiàn)以下的功能:1.創(chuàng)建程序組命令格式為:CreateGroup(程序組名,程序組所在的路徑)程序組不存在時(shí)進(jìn)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論