第七章 剪貼板和動(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)接庫(kù)(DLLs)。這中間前三種方式最為常用,OLE功能最為強(qiáng)大,DDE次之。而剪貼板使用最為方便。在本章,我們只討論剪貼板和動(dòng)態(tài)數(shù)據(jù)交換。利用OLE實(shí)現(xiàn)數(shù)據(jù)交換見下一章,利用動(dòng)態(tài)聯(lián)接庫(kù)(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 包含剪貼板方法的部件
━━━━━━━━━━━━━━━━━━━━━━━━━━━
方 法 部 件
———————————————————————————
TDBEdit TDBMemo
TDBImage
CopyToClipboard TEdit TMemo TMaskEdit
TOLEContainer
TDDEServerItem
———————————————————————————
TDBEdit TDBMemo
CutToClipboard TDBImage
TEdit TMemo TMaskEdit
———————————————————————————
TDBEdit TDBMemo
PasteFromClipboard TDBImage
TEdit 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庫(kù)單元中定義了一個(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 :TPersistent
SetAsHandle Format:Word 把指定格式數(shù)據(jù)的句柄交給剪貼板
返回類型:THandle
GetAsHandle Format:Word 返回剪貼板指定格式數(shù)據(jù)的句柄
返回類型:THandle
HasFormat Format:Word 判斷剪貼板是否擁有給定的格式
返回類型:Boolean
SetTextBuf 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);
var
ARect: TRect;
begin
Clipboard.Assign(Image1.Picture);
with Image.Canvas do
begin
CopyMode := 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);
var
Bitmap: TBitmap;
begin
if Clipboard.HasFormat(CF_BITMAP) then
begin
Bitmap := TBitmap.Create;
try
Bitmap.Assign(Clipboard);
Image.Canvas.Draw(0, 0, Bitmap);
finally
Bitmap.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:
Caption=‘Save Bitmap in Clipboard '
Panel1:
Align = ' Top '
Image1:
Align = ' Client '
SaveDialog1:
FileEditStyle = fsEdit
FileName = '*.bmp'
Filter = 'Bitmap Files(*.bmp)|*.bmp|Any Files(*.*)|*.*'
InitialDir = 'c:\bmp'
Title = 'Save Bitmap'
程序主窗口是TForm派生類TClipSaveForm的實(shí)例。TClipSaveForm通過定義一些私有數(shù)據(jù)成員和過程,使響應(yīng)和處理Windows的相應(yīng)消息成為可能。下面是TClipSaveForm的類定義:
type
TClipSaveForm = 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;
相關(guān)推薦:2010年9月計(jì)算機(jī)等級(jí)考試試題及答案解析專題北京 | 天津 | 上海 | 江蘇 | 山東 |
安徽 | 浙江 | 江西 | 福建 | 深圳 |
廣東 | 河北 | 湖南 | 廣西 | 河南 |
海南 | 湖北 | 四川 | 重慶 | 云南 |
貴州 | 西藏 | 新疆 | 陜西 | 山西 |
寧夏 | 甘肅 | 青海 | 遼寧 | 吉林 |
黑龍江 | 內(nèi)蒙古 |