我寫了一個打印文本文件的類庫,功能包括:打印預覽、打印。打印時可以選擇打印機,可以指定頁碼范圍。調用方法非常簡單:
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;

}

}

}
這些程序都相當簡當明了,這裡就不再解釋了。
這個類庫有個缺點:當文本文件中的一行不能在打印紙的一行中打印完時,該行的後半部就丟失了。