我寫了一個打印文本文件的類庫,功能包括:打印預覽、打印。打印時可以選擇打印機,可以指定頁碼范圍。調用方法非常簡單:
TextFilePrinter p = new TextFilePrinter(tbxFileName.Text);
p.View(); // 打印預覽
p.Print(); // 打印文件
使用 TextFilePrinter 類的以下構造函數可以指定打印時使用的字體:
TextFilePrinter(string fileName, Encoding theEncode, Font theFont)
下面測試程序運行時的截圖:
點擊“預覽”按鈕后:
點擊“打印”按鈕后:
這幅圖中的打印機:“Microsoft Office Doument Image Writer”是 Microsoft Office 2003 軟件提供一個虛擬打印機,用來調試打印程序非常方便(使用“打印預覽”也可以調試打印程序,但“打印預覽”只能使用默認的打印機和默認的打印屬性,也不能設置頁碼范圍),可以設置打印屬性和頁碼范圍以及打印份數。使用它來調試打印程序,可以節省不少打印紙。為建設節約型社會作貢獻 :)
這幅圖就是該虛擬打印機在屏幕上的顯示的結果。
這里是測試程序的源代碼:

// PrintFile.cs - 文件打印程序 // 編譯方法: csc /t:winexe PrintFile.cs TextFilePrinter.cs using System; using System.Drawing; using System.Windows.Forms; using Skyiv.Util; namespace Skyiv.Ben.Test { class PrintFileForm : Form { TextBox tbxFileName; public PrintFileForm() { SuspendLayout(); Button btnFileName = new Button(); btnFileName.Text = "文件名"; btnFileName.Location = new Point(10, 10); btnFileName.Size = new Size(60, 24); btnFileName.Click += new EventHandler(BtnFileName_Click); Button btnPrint = new Button(); btnPrint.Text = "打印"; btnPrint.Location = new Point(75, 10); btnPrint.Size = new Size(60, 24); btnPrint.Click += new EventHandler(BtnPrint_Click); Button btnView = new Button(); btnView.Text = "預覽"; btnView.Location = new Point(140, 10); btnView.Size = new Size(60, 24); btnView.Click += new EventHandler(BtnView_Click); tbxFileName = new TextBox(); tbxFileName.Text = "PrintFile.cs"; tbxFileName.Location = new Point(10, 44); tbxFileName.Size = new Size(190, 20); tbxFileName.ReadOnly = true; tbxFileName.Anchor = (AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right); Controls.AddRange(new Control[]{btnFileName, btnPrint, btnView, tbxFileName}); Text = "文本文件打印程序"; ClientSize = new Size(210, 80); ResumeLayout(false); } void BtnFileName_Click(object sender, EventArgs e) { OpenFileDialog dlg = new OpenFileDialog(); if(dlg.ShowDialog() != DialogResult.OK) return; tbxFileName.Text = dlg.FileName; } void BtnPrint_Click(object sender, EventArgs e) { TextFilePrinter p = new TextFilePrinter(tbxFileName.Text); p.Print(); } void BtnView_Click(object sender, EventArgs e) { TextFilePrinter p = new TextFilePrinter(tbxFileName.Text); p.View(); } static void Main() { Application.Run(new PrintFileForm()); } } }
這里是該類的源代碼:

using System; using System.Drawing; using System.Drawing.Printing; using System.Windows.Forms; using System.IO; using System.Text; namespace Skyiv.Util { sealed class TextFilePrinter { string fileName; Encoding theEncode; Font theFont; StreamReader srToPrint; int currPage; public TextFilePrinter(string fileName) : this(fileName, Encoding.GetEncoding("GB18030"), new Font("新宋體", 10)) { } public TextFilePrinter(string fileName, Encoding theEncode, Font theFont) { this.fileName = fileName; this.theEncode = theEncode; this.theFont = theFont; } public void Print() { using (srToPrint = new StreamReader(fileName, theEncode)) { PrintDialog dlg = new PrintDialog(); dlg.Document = GetPrintDocument(); dlg.AllowSomePages = true; dlg.AllowPrintToFile = false; if (dlg.ShowDialog() == DialogResult.OK) dlg.Document.Print(); } } public void View() { using (srToPrint = new StreamReader(fileName, theEncode)) { PrintPreviewDialog dlg = new PrintPreviewDialog(); dlg.Document = GetPrintDocument(); dlg.ShowDialog(); } } PrintDocument GetPrintDocument() { currPage = 1; PrintDocument doc = new PrintDocument(); doc.DocumentName = fileName; doc.PrintPage += new PrintPageEventHandler(PrintPageEvent); return doc; } void PrintPageEvent(object sender, PrintPageEventArgs ev) { string line = null; float linesPerPage = ev.MarginBounds.Height / theFont.GetHeight(ev.Graphics); bool isSomePages = ev.PageSettings.PrinterSettings.PrintRange == PrintRange.SomePages; if (isSomePages) { while (currPage < ev.PageSettings.PrinterSettings.FromPage) { for (int count = 0; count < linesPerPage; count++) { line = srToPrint.ReadLine(); if (line == null) break; } if (line == null) return; currPage++; } if (currPage > ev.PageSettings.PrinterSettings.ToPage) return; } for (int count = 0; count < linesPerPage; count++) { line = srToPrint.ReadLine(); if (line == null) break; ev.Graphics.DrawString(line, theFont, Brushes.Black, ev.MarginBounds.Left, ev.MarginBounds.Top + (count * theFont.GetHeight(ev.Graphics)), new StringFormat()); } currPage++; if (isSomePages && currPage > ev.PageSettings.PrinterSettings.ToPage) return; if (line != null) ev.HasMorePages = true; } } }
這些程序都相當簡當明了,這里就不再解釋了。
這個類庫有個缺點:當文本文件中的一行不能在打印紙的一行中打印完時,該行的后半部就丟失了。