?? 019.htm
字號:
</font><p>procedure TForm1.Cut1Click(Sender: TObject);</p>
<p>var</p>
<p>ARect: TRect;</p>
<p>begin</p>
<p>Clipboard.Assign(Image1.Picture);</p>
<p>with Image.Canvas do</p>
<p>begin</p>
<p>CopyMode := cmWhiteness; </p>
<p>ARect := Rect(0, 0, Image.Width, Image.Height); </p>
<p>CopyRect(ARect, Image.Canvas, ARect); </p>
<p>CopyMode := cmSrcCopy; </p>
<p>end;</p>
<p>end;<font face="宋體" lang="ZH-CN"> </font></p>
<p>7.1.3.3 <font face="宋體" lang="ZH-CN">粘貼 </p>
<p>從剪貼板上粘貼圖像,首先檢測剪貼板上的數據格式。如果格式為</font>CF_BITMAP<font
face="宋體" lang="ZH-CN">,則調用目標位圖的</font>Assign <font face="宋體"
lang="ZH-CN">方法粘貼圖像。</p>
<p>程序清單如下。</p>
</font><p>procedure TForm1.PasteButtonClick(Sender: TObject);</p>
<p>var</p>
<p>Bitmap: TBitmap;</p>
<p>begin</p>
<p>if Clipboard.HasFormat(CF_BITMAP) then </p>
<p>begin</p>
<p>Bitmap := TBitmap.Create; </p>
<p>try</p>
<p>Bitmap.Assign(Clipboard); </p>
<p>Image.Canvas.Draw(0, 0, Bitmap); </p>
<p>finally</p>
<p>Bitmap.Free;</p>
<p>end;</p>
<p>end;</p>
<p>end; </p>
<p>try...finally<font face="宋體" lang="ZH-CN">為資源保護塊,參第十二章。</p>
</font><p>7.1.4 <font face="宋體" lang="ZH-CN">建立自己的剪貼板觀察程序 </p>
</font><p><font face="宋體" lang="ZH-CN">
在這一節中我們要建立一個自己的剪貼板觀察程序,用來保存截獲到剪貼板中的位圖。</p>
</font><p> Windows<font face="宋體" lang="ZH-CN">允許用戶建立自己的剪貼板觀察程序,并把該程序添加到一個剪貼板觀察器鏈中。在鏈中,位置靠前的程序有義務把有關剪貼板的消息傳遞到緊隨其后的觀察程序。而處于鏈首的程序由</font>Windows<font
face="宋體" lang="ZH-CN">的消息循環機制直接把剪貼板消息發送過來。</p>
</font><p><font face="宋體" lang="ZH-CN">
建立一個剪貼板觀察程序,首先該程序必須能響應相應的</font>Windows<font
face="宋體" lang="ZH-CN">消息。對于那些熟悉</font>Microsoft<font face="宋體"
lang="ZH-CN">公司</font>Visual Basic<font face="宋體" lang="ZH-CN">的讀者來說,這是令他們頭疼而束手無策的地方。但</font>Delphi<font
face="宋體" lang="ZH-CN">在這方面卻有良好的表現:利用關鍵字</font>message<font
face="宋體" lang="ZH-CN">,用戶可以將一個過程定義為響應特定的</font>Windows<font
face="宋體" lang="ZH-CN">消息。如: </p>
</font><p>procedure WMDrawClipboard(var Msg:TWMDrawClipboard);</p>
<p>message WM_DRAWCLIPBOARD; </p>
<p><font face="宋體" lang="ZH-CN">
可以響應</font>WM_DRAWCLIPBOARD<font
face="宋體" lang="ZH-CN">消息。類</font>TWMDrawClipboard<font face="宋體"
lang="ZH-CN">是消息類</font>Message <font face="宋體" lang="ZH-CN">的子類。</font>Delphi<font
face="宋體" lang="ZH-CN">把所有的消息都重新進行了定義,使用戶在使用時可以直接引用其便于記憶的數據成員,而不必再自己動手去分解消息。雖然這并不能算作是一個重大的改進,但卻體現了</font>Delphi<font
face="宋體" lang="ZH-CN">處處為用戶方便著想的特點。</p>
</font><p><font face="宋體" lang="ZH-CN">
我們將要建立的程序目的是把截獲到剪貼板上的位圖保存下來。在本書的寫作過程中,這一工作是大量存在的。雖然利用</font>Windows<font
face="宋體" lang="ZH-CN">工具</font>PaintBrush(<font face="宋體" lang="ZH-CN">畫筆),通過粘貼、保存等操作可以實現這一功能,但卻存在以下一些問題:</p>
</font><p>1.<font face="宋體" lang="ZH-CN">程序頻繁切換影響效率,當有大量位圖存在時更是如此;</p>
</font><p>2.<font face="宋體" lang="ZH-CN">畫筆有一個很討厭的缺陷:當剪貼板上的位圖比畫筆界面的客戶區大時,客戶區外的位圖被截斷。因而往往需要根據所截獲位圖的大小來調整畫筆客戶區的大小,并重新進行粘貼。而如果開始就把畫筆客戶區調整到足夠大,又會覆蓋掉屏幕上一些有用的信息。</p>
</font><p><font face="宋體" lang="ZH-CN">
為解決這些問題,我開發了下面的程序。程序啟動時,以極小化方式運行。此時只要剪貼板中存入位圖,則自動彈出一個對話框請求用戶保存。如果用戶希望查看確認,則可以雙擊運行程序圖標,選擇相應按鈕,剪貼板中的位圖就會顯示在屏幕上。</font></p>
<font face="宋體" lang="ZH-CN"><p>部件關鍵屬性設計如下: </p>
</font><p>ClipSaveForm<font face="宋體" lang="ZH-CN">:</p>
</font><p>Caption<font face="宋體" lang="ZH-CN">=‘</font>Save Bitmap in Clipboard '</p>
<p>Panel1:</p>
<p>Align = ' Top '</p>
<p>Image1:</p>
<p>Align = ' Client '</p>
<p>SaveDialog1:</p>
<p>FileEditStyle = fsEdit</p>
<p>FileName = '*.bmp'</p>
<p>Filter = 'Bitmap Files(*.bmp)|*.bmp|Any Files(*.*)|*.*'</p>
<p>InitialDir = 'c:\bmp'</p>
<p>Title = 'Save Bitmap' </p>
<p><font face="宋體" lang="ZH-CN">
程序主窗口是</font>TForm<font
face="宋體" lang="ZH-CN">派生類</font>TClipSaveForm<font face="宋體" lang="ZH-CN">的實例。</font>TClipSaveForm<font
face="宋體" lang="ZH-CN">通過定義一些私有數據成員和過程,使響應和處理</font>Windows<font
face="宋體" lang="ZH-CN">的相應消息成為可能。下面是</font>TClipSaveForm<font
face="宋體" lang="ZH-CN">的類定義: </p>
</font><p>type</p>
<p>TClipSaveForm = class(TForm)</p>
<p>SaveDialog1: TSaveDialog;</p>
<p>Image1: TImage;</p>
<p>Panel1: TPanel;</p>
<p>Button1: TButton;</p>
<p>SpeedButton1: TSpeedButton;</p>
<p>SpeedButton2: TSpeedButton;</p>
<p>Button2: TButton;</p>
<p>procedure FormCreate(Sender: TObject);</p>
<p>procedure FormDestroy(Sender: TObject);</p>
<p>procedure Button1Click(Sender: TObject);</p>
<p>procedure Button2Click(Sender: TObject);</p>
<p>procedure SpeedButton1Click(Sender: TObject);</p>
<p>procedure SpeedButton2Click(Sender: TObject);</p>
<p>private</p>
<p>{ Private declarations }</p>
<p>MyBitmap: TBitmap; { <font face="宋體" lang="ZH-CN">保存截獲的位圖</font> }</p>
<p>View: Boolean; { <font face="宋體" lang="ZH-CN">判斷是否顯示</font> }</p>
<p>NextViewerHandle: HWND; { <font face="宋體" lang="ZH-CN">下一剪貼板觀察器的句柄</font>
}</p>
<p>procedure WMDrawClipboard(var Msg:TWMDrawClipboard);</p>
<p>message WM_DRAWCLIPBOARD;</p>
<p>procedure WMChangeCBChain(var Msg:TWMChangeCBChain);</p>
<p>message WM_CHANGECBCHAIN; </p>
<p>{ <font face="宋體" lang="ZH-CN">響應</font>Windows<font face="宋體" lang="ZH-CN">的剪貼板消息</font>
}</p>
<p>public</p>
<p>{ Public declarations }</p>
<p>end;</p>
<p><font face="宋體" lang="ZH-CN">
窗口創建時,把該窗口登錄為剪貼板觀察器,添加到剪貼板觀察器鏈中,同時進行變量、部件和剪貼板的初始化。 </p>
</font><p>procedure TClipSaveForm.FormCreate(Sender: TObject);</p>
<p>begin</p>
<p>View := False;</p>
<p>SpeedButton2.Down := True;</p>
<p>MyBitmap := TBitmap.create;</p>
<p>try</p>
<p>MyBitmap.Width := 0;</p>
<p>MyBitmap.Height := 0 ;</p>
<p>except</p>
<p>Application.terminate;</p>
<p>end;</p>
<p>Clipboard.Clear;</p>
<p>NextViewerHandle := SetClipboardViewer(Handle);</p>
<p>end; </p>
<p><font face="宋體" lang="ZH-CN">窗口關閉時,退出剪貼板觀察器鏈,并釋放內存: </p>
</font><p>procedure TClipSaveForm.FormDestroy(Sender: TObject);</p>
<p>begin</p>
<p>ChangeClipboardChain(Handle,NextViewerHandle);</p>
<p>MyBitmap.Free;</p>
<p>end; </p>
<p><font face="宋體" lang="ZH-CN">在以上兩段程序中用到的兩個</font>Windows
API<font face="宋體" lang="ZH-CN">函數</font>SetClipboardViewer<font face="宋體"
lang="ZH-CN">和</font>ChangeClipboardChain<font face="宋體" lang="ZH-CN">分別用于登錄和退出剪貼板觀察器鏈。</p>
<p>程序保存位圖的功能是在消息響應過程WMDrawClipboard中實現的。該過程在剪貼板內容有變化時被調用。 </p>
</font><p>procedure TClipSaveForm.WMDrawClipboard(var Msg: TWMDrawClipboard);</p>
<p>var</p>
<p>FileName: String;</p>
<p>begin</p>
<p>If NextViewerHandle <> 0 then</p>
<p>SendMessage(NextViewerHandle,msg.Msg,0,0);</p>
<p>If ClipBoard.HasFormat(CF_BITMAP) then</p>
<p>begin</p>
<p>MyBitmap.Assign(Clipboard);</p>
<p>If SaveDialog1.Execute then</p>
<p>begin</p>
<p>FileName := SaveDialog1.FileName;</p>
<p>MyBitmap.SaveToFile(FileName);</p>
<p>end;</p>
<p>If View then</p>
<p>begin</p>
<p>WindowState := wsNormal;</p>
<p>Image1.Picture.Bitmap := MyBitmap;</p>
<p>end;</p>
<p>end;</p>
<p>Msg.Result := 0;</p>
<p>end; </p>
<p><font face="宋體" lang="ZH-CN">
程序首先判斷在剪貼板觀察器鏈中是否還存在下一個觀察器。如果有,則把消息傳遞下去,這是剪貼板觀察器程序的義務。而后判斷剪貼板上內容的格式是否為位圖。如是,則首先把剪貼板上內容保存到數據成員</font>MyBitmap<font
face="宋體" lang="ZH-CN">中,并激活一個文件保存對話框把位圖保存到文件中。如果</font>View=True<font
face="宋體" lang="ZH-CN">,則把窗口狀態</font>(WindowState)<font face="宋體"
lang="ZH-CN">設置為</font>wsNormal<font face="宋體" lang="ZH-CN">,并把</font>MyBitmap<font
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -