Delphi 打印 TPrinter

   打印
         打印對於許多 Windows 程序員來說是十分棘手的問題。

        Delphi 簡化了打印時用戶所必須瞭解的大部分內容。用戶可以很輕鬆地寫出簡單的打印程序來輸出文本和位圖化了的圖像。
對於更爲複雜的打印,僅需瞭解幾個要領和技術,用戶就可以實現任何類型的自定義打
印。
當了解了這些後,打印也就不那麼困難了。
Delphi 的TPrinter對象封裝了 Windows 的打印引擎,爲程序員做了大量原本需要親自做的工作。

本章告訴用戶怎樣用TPrinter來完成各種打印作業。用戶可以看到一個簡單的例子,
從中可以瞭解到創建高級打印程序的技術,而這些技術正是用戶成爲打印高手的起點。

5.1  TPrinter 對象
        Delphi 中的 TPrinter類可以方便地實現通常的打印任務。通過Printer 全局函數可以返回TPrinter類的一個對象,該對象在Printers單元中定義。

       可以把Printer 全局函數看作一個全局變量,並利用這個全局變量來與打印機進行打印操作。
利用 Printer 來實現打印的一般過程如下:
1)調用BeginDoc 過程向打印機發送一個打印作業(此時還沒有在打印機上開始打
印)。
(2)通過一個 Text 變量或調用 Canvas 對象方法建立打印輸出。
(3)調用 EndDoc過程結束當前的打印作業,該打印作業開始在打印機上打印。
(4)如果出現問題,調用 Abort過程取消當前打印的作業。
表5-1 所示是 TPrinter對象的幾個常用屬性:


表5-1  TPrinter對象的常用屬性
屬性  作用
Aborted  判斷是否中止打印作業
Canvas  畫布屬性
Capabilities  當前打印機驅動設備的設置信息
Copies  打印的份數
Fonts  字體屬性
Handle  打印機句柄
Orientation  紙張的方向:橫向或縱向
PageHeight  紙張的高度
PageNumber  當前打印的頁數
PageWidth  紙張的寬度
Printers  系統中安裝的所有打印機
Printing  標識是否正在進行一個打印作業
PrinterIndex  打印機屬性中當前打印機的索引值

表5-2 所示是 TPrinter對象的幾個常用方法
表5-2  TPrinter的方法
方法  作用
Abort  中止正在打印的打印作業
BeginDoc  向打印機發送一個打印作業
EndDoc  結束當前的打印作業並關閉文本文件變量
GetPrinter  獲得當前打印機序號
NewPage  開始新的一頁並增加 PageNumber屬性
Refresh  更新字體和打印機的屬性


通常,在打印前要進行打印預覽。在打印預覽的時候,往往要將打印的結果在屏幕上顯示出來。

這時,就要注意屏幕的分辨率和打印機的分辨率的差別了。讀取屏幕信息可以通過全局變量 Screen 來實現,Screen 爲TScreen類的一個實例,在創建工程的時候就自動創建了,並在程序開始運行時讀取了屏幕的一些設置信息。

值得注意的一點是 TPrinter.Canvas。TPrinter.Canvas 對於窗體來說像一個畫布,在它上面可以顯示文本和圖形

         不同的是, TPrinter.Canvas 表示的是打印輸出的畫布,而非顯示用的畫布。大多數用來顯示文本、圖像和畫圖的程序可以用同一種方式來打印輸出。

         但是,在打印時必須考慮到其中的不同之處:
        ¾  在屏幕上繪畫是動態的,可以擦去在屏幕上輸出的內容。而向打印機中輸出則不那麼靈活,凡是向 TPrinter.Canvas 輸出的內容將被打印機打印出來。
       ¾  在屏幕上顯示文本和圖是很快的,而向打印機輸出,即使是高性能的激光打印機,也是較慢的。因此,必須允許用戶能夠終止打印作業或者採用其他辦法來放棄打印作業。
      ¾  由於用戶運行的是 Windows,可以假定支持圖形顯示。但是,不能對他們的打印機做同樣的假定。一些打印機也許具有非常低的分辨率,或者根本不支持圖形打印。在打印程序中必須考慮到這些問題。
       ¾  用戶從來沒有看到過諸如“顯示超出屏幕空間”、“請插入更多的屏幕空間”此類的信息,但是肯定見過“打印紙不夠”的信息。當這些錯誤發生時, Windows NT/2000 和Windows 95/98能夠處理這些錯誤,但程序員應該向用戶提供在發生這些問題時取消打印的辦法。
        ¾  對於屏幕上的文本和圖形來說,硬拷貝操作看起來是不同的。打印機和顯示器具有非常不同的分辨率。300×300 的位圖在 640×480 的顯示器中顯得很漂亮。但是在300dpi 的激光打印機上,它僅僅是一個1×1 inch 的小方塊。程序員必須負責調整打印程序,使用戶不必用放大鏡就可以看清他們的打印輸出。


5.2   打印操作常用函數
表5-3  Windows API打印操作常用函數
函數  說明
AbortPrinter  在假脫機的情況下刪除打印緩衝文件
AbortProc  當打印作業取消時調用的一個應用程序定義的回調函數
AddForm  爲指定的打印機從有效窗體列表中新增一個窗體
AddJob  獲取一個文件名用來保存打印緩衝工作
AddMonitor  新安裝一個打印機管理器
AddPort  新增一個打印機端口
AddPrinter  在指定的服務器上新安裝一個打印機
AddPrinterConnection  在當前用戶和指定的打印機之間建立一個聯繫
AddPrinterDriver  爲本地或網絡打印機安裝打印機驅動程序
AddPrintProcessor  在指定的打印服務器上安裝一個打印處理器
AddPrintProvidor  新增一個打印機支持器
AdvancedDocumentProperties  設置打印機的高級屬性
ClosePrinter  關閉指定的打印機
ConfigurePort  通過端口設置對話框來設置指定服務器上的端口
ConnectToPrinterDlg  顯示一個瀏覽對話並與網絡打印機連接
DeleteForm  從窗體列表中刪除一個窗體名稱
DeleteMonitor  刪除打印機監視器
DeletePort  刪除打印機端口
DeletePrinter  刪除指定的打印機對象
DeletePrinterConnection  刪除一個打印機連接
DeletePrinterData  刪除打印機的配置數據
DeletePrinterDriver  刪除指定打印機的驅動程序
DeletePrintProcessor  刪除一個打印機的處理器
DeletePrintProvidor  刪除一個打印機的支持器
DocumentProperties  取得或設置打印機的初始化信息或顯示打印機配置對話框
EndDocPrinter  結束指定打印機上的打印作業
EndPagePrinter  在指定打印機上結束一頁並開始新的一頁
EnumForms  列舉打印機支持的窗體信息
EnumJobs  獲取打印機的作業信息
EnumMonitors  獲取指定服務器上的打印監視器信息
EnumMonitors  獲取指定服務器上的打印監視器信息
EnumPorts  列舉指定服務器上支持的端口信息
GetPrinter  獲取指定打印機的信息
GetPrinterData  獲取指定打印機的配置信息
GetPrinterDriver  獲取指定打印機驅動程序的數據信息
GetPrinterDriverDirectory  獲取指定打印機驅動程序所在的目錄
GetPrintProcessorDirectory  獲取指定服務器上打印處理器所在的目錄
OpenPrinter  獲取指定打印機或服務器的句柄
128   第5 章   打印
  (續表)
函數  說明
PrinterMessageBox  顯示打印異常信息對話框
PrinterProperties  顯示指定打印機的屬性對話框
ReadPrinter  從指定的打印機讀取數據
ResetPrinter  設置打印機的數據類型和設備模式等
ScheduleJob  獲取指定打印作業的打印緩衝時間表
SetForm  設置指定打印機的窗體信息
SetJob  暫停、繼續、取消和重新開始指定打印機上的打印作業
SetPort  設置打印機端口的狀態
SetPrinter  設置打印機的狀態信息
SetPrinterData  設置打印機的配置信息
StartDocPrinter  通知打印緩衝器一個打印作業將被送往打印
StartPagePrinter  通知打印緩衝器一個頁面將送往打印
WritePrinter  通知打印緩衝器數據將被寫到指定的打印機


5.3   打印操作
這一節我們爲讀者介紹實現簡單的打印輸出的方法。
5.3.1   打印文本
         在Delphi 中實現文本的打印功能需要做的只是取得打印參數,打開打印機,然後發送文本的每一行內容。

         在 Delphi 中提供了一個 Printers程序單元,它說明了一個 TPrint 對象,封裝了Windows 打印工作和輸出打印機之間的接口,並提供常用的屬性和方法,其中畫布Canvas 是一個非常有用的屬性,它代表了當前打印文件的表面,是以圖形方式來工作的,整個的打印輸出工作僅僅是將用戶打印的內容輸出到TPrinter的屬性 Canvas 上,當全部的輸出工作完成之後,打印對象(TPrinter)把 Canvas 的屬性值送到打印機上。


一個例子:在 Form中加入 Memo,PrintDialog,PrintSetupDialog 和兩個 Button 控件,兩個Button 的Caption分別爲“打印設置”和“打印”。然後編寫Button 的事件驅動程序如下:

  1. implement   
  2. uses printers;   
  3. {$R *.DFM}   
  4. procedure TForm1.BitBtn1Click(Sender:TObject);   
  5. begin   
  6.   PrinterSetupDialog1.Execute;//選擇輸出的打印機以及其他打印控制選項   
  7. end;   
  8. procedure TForm1.BitBtn2Click(Sender:TObject);   
  9. var   
  10.   lines:integer;   
  11.   prntext:system.text;   
  12. // 將prntext 聲明爲一個在system 程序單元中定義的文本文件   
  13. begin   
  14.   if PrintDialog1.Execute then   
  15. assignprn(prntext);// 將prnsetup分配給打印機   
  16. rewrite(prntext);// 調用rewrite 函數,爲輸出打開已分配的文件   
  17. printer.Canvas.font:=memo1.font;   
  18. // 把當前Memo1的字體指定給打印對象的Canvas 的字體屬性   
  19. for lines:=0 to memo1.lines.count-1 do   
  20.   writeln(prntext,memo1.lines[lines]);   
  21. // 把Memo的內容寫到打印機對象   
  22. System.close(prntext);   
  23. end;   
  24. procedure Tform1.FormCreate(Sender:TObject);   
  25. begin   
  26.   memo1.lines.loadfromfile(‘C:\dos\os2.txt’);   
  27.   // 在Form建立時讀入文件C:\dos\os2.txt   
  28. end;   

 

 

5.3.2   打印位圖
打印位圖也很簡單。下面列出了相應代碼。

  1. procedure TBMPForm.mmiPrintClick(Sender:TObject)   
  2. begin   
  3.   inherited;   
  4.     with ImgMain.Picture.BitMap do   
  5.   begin   
  6.     Printer.BeginDoc;   
  7.     Printer.Cavas.StretchDraw(Cava s.ClipRect,ImgMain.Picture.Bitmap);   
  8.     Printer.EndCode;   
  9.   end;   
  10. end;   

 

調用 TCanvas.StretchDraw()來打印位圖僅需三行代碼。

在Delphi 中,位圖的默認格式是DIB 格式,而 DIB 格式正是打印機驅動程序所需要的,這就大大簡化了打印位圖的工作。

如果遇到一個非DIB 格式的位圖,可以把它複製給一個臨時的TBitmap 對象,然後把TBitmap.HandleType 特性設爲 bmDIB ,以強制把位圖臨時轉化爲 DIB 格式,這樣就可以打印出DIB 格式的位圖。注意打印的關鍵之一是打印圖像時能夠以其與在屏幕上近似相同的尺寸打印。

例如,一個3×3inch的圖像在 640×480 的屏幕上要比在 300dpi 的打印機上需要較少的像素。因此,在調用 StretchDIBits()時,把位圖位伸以便與 TPrinter.Canvas 匹配。

5.3.3   打印 TMemo組件中的內容
事實上,用 AssignPrn()來打印文本行相當簡單。AssignPrn() 可以爲當前打印機分配一個文本文件變量,它與 Rewrite() 和CloseFile()等過程一起使用。下面幾行代碼說明了用法:
var
f:TextFile;
begin
AssignPrn(f);
try
Rewrite(f);
Writeln(f, 'Print the output');
finally
CloseFile(f);
end;
end;
向打印輸出一行文字與向文件中輸出一行文字一樣,可以使用下面的語句:
Writeln(f,'This is my line of text');
下面的一段程序演示瞭如何從 TMdiEditForm 打印窗體上的內容。用戶可以用同樣的技術來打印任何文本。

  1. procedure TForm1.mmiPrintClick(Sender:TObject)   
  2. var   
  3.   i:integer;   
  4.   PText:TextFile;   
  5. begin   
  6.   inherited;   
  7.   if PrintDialog.Execute then   
  8.   begin   
  9.     AssignPrn(PText);   
  10.     Rewrite(PText);   
  11.     try   
  12.       Printer.Cavas.Font:=memMainMemo.Font;   
  13.       for i:=0 to memMainMemo.Lines.Count-1 do   
  14.         writeln(PText,memMainMemo.Line[i]);   
  15.     finally   
  16.       CloseFile(PText);   
  17.     end;   
  18.   end;   
  19. end;   

 

注意打印機的字體被指定爲TMemo組件的字體,導致打印輸出的字體與memMainMemo的字體一樣。只有指定打印機所支持的字體,打印機才能以指定的字體打印。否則打印機以與指定字體特徵最接近的字體打印。


5.3.4   打印 RTF 格式的文本
RTF 格式文本的打印同樣簡單,只要調用一個方法就行了。相應代碼如下所示:
procedure TMdiRtfForm.mmiPrintClick(Sender:TObject);
begin
inherited;
reMain.Print(Caption);
end;


5.4   打印技巧
5.4.1   獲取顯示當前打印機的分辨率
Windows 下的打印分辨率對打印程序有至關重要的作用,利用函數 GetDeviceCaps() 可以得到打印分辨率。
例如:
var
  iHorizontal,iVertical:integer;
  iHorizontal:=GetDeviceCap s(printer.handle,LOGPIXELSX);
  iVertical:= GetDeviceCaps(printer.handle,LOGPIXELSY);
begin
  ShowMessage( '水平分辨率:'+inttostr(iHorizontal)+chr(12)+ ' 垂直分辨率:'+Inttostr(iVertical));
end;


5.4.2   儘量不要使用 AssignPrn
儘管 AssignPrn簡化了文本打印操作,是輸出到打印機像輸出到文件一樣簡單。但簡單帶來的是一系列不方便:用戶無法知道當前打印的行數,無法準確控制行距,也無法靈活改變字體字型,所以最好使用 Canvas 屬性。

5.4.3   用打印機的點數做度量單位
如果要讓打印程序在任何打印機上都能正常打印,就必須改變用戶的度量單位。如果採用固定度量,不同分辨率打印效果是不同的。舉例來說:printer.Canvas.rectangle(0,0,360,720)
在佳能 4200SP上能打出一個 1 inch  寬,2 inch  高的矩形,但在 600×600de HP6L上只能打出0.6 inch  寬,1.2inch  高的矩形。使用打印機的點數作爲度量單位是一個明智的選擇。具
體做法如下:

  1. var   
  2.   PointX:integer;   
  3.   PointY:integer;   
  4. Begin   
  5.     PointX := GetDeviceCap s(printer.Handle,LOGPIXELSX);   
  6.     PointY := GetDeviceCap s(printer.Handle,LOGPIXELSY);   
  7.   Printer.Canvas.rectangle(0,0,PointX*1,PointY*2);   
  8. End;   

 

這樣,無論使用什麼打印機,都能得到一個1 inch  寬,2 inch  高的矩形。


5.4.4   將打印結果直接送到打印機
Delphi 提供了兩種打印方式:

           一種將結果輸出到Form,再調試 Form的Print 方法將結果輸送給打印機。如果用戶採用第一種方式,則無論用戶怎樣調整Form的PrintScal 屬性,打印出來的東西也不能讓用戶滿意,所以建議使用第二種方式。


5.4.5   獲取默認打印機的信息
在Windows 的Win.ini 文件中有下面的一些配置信息:
[Window]
load=
run=
NullPort=None;
Device=HP LaserJet III,HPPCL5MS,LPT1:

其中windows 節的Device 鍵中默認打印機的信息,可以通過 Windows API 函數
GetProfileString獲取該信息。函數 GetProfileString的原型如下:
DWORD GetProfileString(
  LPCTSTR lpAppName,    // 指定節名的字符串
  LPCTSTR lpKeyName,    // 指定鍵名的字符串
LPCTSTR lpDefault,   // 沒有找到鍵名返回的字符串
LPCTSTR lpReturnString,    // 找到鍵名返回的字符串
DWORD nSize    //lpReturnedString的字節數
);


5.5   本章小結
本章介紹了 Windows 程序中實現打印的方法。

首先介紹了TPrint 類,講述了TPrint 類的一些常用屬性和常用函數,尤其着重介紹了Canvas 屬性。接下來介紹了打印操作常用函數。

然後是一些基本的打印操作,分別介紹了文本文件,位圖文件,TMemo組件和 RTF 格式的文件的打印,最後介紹了處理打印問題時的技巧和注意事項。

打印是應用程序通常具備的功能之一,通過這一部分知識的學習,有助於讀者編寫出功能全面的應用程序。
發佈了48 篇原創文章 · 獲贊 15 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章