使用 Windows 窗体打印
重要的打印类:
| PrintDocument |
PrintDocument 用于将输出发送到打印机。可实例化一个 PrintDocument,设置一些属性描述打印的内容,然后调用 Print 方法。PrintDocument 为要打印的每一页引发 PrintPage 事件。可向此事件的事件处理程序添加打印逻辑。 |
| PrinterSettings |
有关应如何打印文档的信息。这包括在哪个打印机上打印该文档。 |
| PageSettings |
有关应如何打印页的信息。 |
| PrintPageEventArgs |
PrintDocument 上 PrintPage 事件的数据。它为打印图面提供剪辑矩形和 Graphics 对象。 |
| PrintEventArgs |
PrintDocument 上 BeginPrint 和 EndPrint 事件的数据。允许取消打印作业。 |
| PrintDialog |
打印机选项对话框。包装 Win32 PrintDlg API。 |
| PageSetupDialog |
页属性对话框。包装 Win32 PageSetupDlg API。 |
| PrintPreviewControl |
显示 PrintDocument 的控件。允许创建打印预览对话框。 |
| PrintPreviewDialog |
通过使用 PrintPreviewControl 显示 PrintDocument 的对话框。 |
| PrintController |
PrintController 控制如何打印 PrintDocument。PrintDocument.Print 使用打印控件呈现文档。 .NET 框架提供两个打印控制器:
通常,从来不必实现 PrintController。仅当要呈现到其他图面时才实现 PrintController。 |
生成进行打印的应用程序
了解打印类如何组合在一起的最简单的途径就是尝试完成一个简单示例,将一个文本文件的内容输出到打印机。
第 1 步:打印逻辑
需要做的第一件事是编写打印逻辑。这可通过处理 PrintDocument 上的事件来完成。当调用 PrintDocument.Print() 方法时,引发下列事件:
- BeginPrint
- PrintPage(一个或多个)
- EndPrint
PrintPage 事件的参数类型 (PrintPageEventArgs) 具有 HasMorePages 属性。如果在事件处理程序返回时,此属性设置为 true,则 PrintDocument 设置新页并再次引发 PrintPage 事件。
因此,PrintPage 事件处理程序中的逻辑基本上是:
- 使用事件参数中的信息打印页的内容。这些事件参数包含打印机的 Graphics、该页的 PageSettings、页的边界以及边距的大小。
- 确定是否还要打印其他页。
- 如果还有其他页,则将 HasMorePages 设置为 true。
- 如果没有其他页,则将 HasMorePages 设置为 false。
在最简单的情况下,可以作为包含打印请求的 Form 的一部分创建 PrintDocument 和处理 PrintPage 事件。
//Example Form that Prints
public class PrintCtl : Form {
Private string[] printBuffer ;
Private Font printFont;
Private int startLine;
//Event fired when the user presses the print button
private void print_Click(object sender, EventArgs e) {
fileToPrint = new StreamReader ("PrintMe.Txt");
try {
printFont = new Font("Arial", 10);
PrintDocument pd = new PrintDocument(); //Assumes the default printer
pd.PrintPage += new PrintPageEventHandler(this.pd_PrintPage);
pd.Print();
} finally {
fileToPrint.Close() ;
}
}
//Event fired for each page to print
private void pd_PrintPage(object sender, PrintPageEventArgs ev) {
float lpp = 0 ;
float yPos = 0 ;
int count = 0 ;
float leftMargin = ev.MarginBounds.Left;
float topMargin = ev.MarginBounds.Top;
String line=null;
//Work out the number of lines per page
//Use the MarginBounds on the event to do this
lpp = ev.MarginBounds.Height / printFont.GetHeight(ev.Graphics) ;
//Now iterate over the file printing out each line
//NOTE WELL: This assumes that a single line is not wider than the page width
//Check count first so that we don't read line that we won't print
while (count < lpp && ((line=streamToPrint.ReadLine()) != null)) {
yPos = topMargin + (count * printFont.GetHeight(ev.Graphics));
//Print Preview control will not work.
ev.Graphics.DrawString (line, printFont, Brushes.Black, leftMargin,
yPos, new StringFormat());
count++;
}
//If we have more lines then print another page
if (line != null)
ev.HasMorePages = true ;
else
ev.HasMorePages = false ;
}
....
}
Public Class PrintingExample1
Inherits System.Windows.Forms.Form
....
private printFont As Font
private streamToPrint As StreamReader
Public Sub New ()
MyBase.New
InitializeComponent()
End Sub
'Event fired when the user presses the print button
Private Sub printButton_Click(sender As object, e As System.EventArgs)
Try
streamToPrint = new StreamReader ("PrintMe.Txt")
Try
printFont = new Font("Arial", 10)
Dim pd as PrintDocument = new PrintDocument() 'Assumes the default printer
AddHandler pd.PrintPage, AddressOf Me.pd_PrintPage
pd.Print()
Finally
streamToPrint.Close()
End Try
Catch ex As Exception
MessageBox.Show("An error occurred printing the file - " + ex.Message)
End Try
End Sub
'Event fired for each page to print
Private Sub pd_PrintPage(sender As object, ev As System.Drawing.Printing.PrintPageEventArgs)
Dim lpp As Single = 0
Dim yPos As Single = 0
Dim count As Integer = 0
Dim leftMargin As Single = ev.MarginBounds.Left
Dim topMargin As Single = ev.MarginBounds.Top
Dim line as String
'Work out the number of lines per page
'Use the MarginBounds on the event to do this
lpp = ev.MarginBounds.Height / printFont.GetHeight(ev.Graphics)
'Now iterate over the file printing out each line
'NOTE WELL: This assumes that a single line is not wider than the page width
'Check count first so that we don't read line that we won't print
line=streamToPrint.ReadLine()
while (count < lpp AND line <> Nothing)
yPos = topMargin + (count * printFont.GetHeight(ev.Graphics))
'Print Preview control will not work.
ev.Graphics.DrawString (line, printFont, Brushes.Black, leftMargin, _
yPos, new StringFormat())
count = count + 1
if (count < lpp) then
line=streamToPrint.ReadLine()
end if
End While
'If we have more lines then print another page
If (line <> Nothing) Then
ev.HasMorePages = True
Else
ev.HasMorePages = False
End If
End Sub
....
End Class
| ||
| C# | VB | |
查看并运行此示例。
[运行示例] | [查看源代码] |
第 2 步:定义自己的打印文档
对于复杂的打印作业或要在多个窗体间重复使用的打印逻辑,可以从 PrintDocument 派生一个新类,并将打印逻辑封装到该类中。在这种情况下,请通过重写 OnPrintPage 方法而不是使用事件处理程序来处理 PrintPage 事件。
public class TextFilePrintDocument : PrintDocument {
private Font printFont = null ;
private StreamReader streamToPrint = null ;
public TextFilePrintDocument(StreamReader streamToPrint) : base () {
this.streamToPrint = streamToPrint ;
}
//Override OnBeginPrint to set up the font we are going to use
protected override void OnBeginPrint(PrintEventArgs ev) {
base.OnBeginPrint(ev) ;
printFont = new Font("Arial", 10);
}
//Override the OnPrintPage to provide the printing logic for the document
protected override void OnPrintPage(PrintPageEventArgs ev) {
base.OnPrintPage(ev) ;
float lpp = 0 ;
float yPos = 0 ;
int count = 0 ;
float leftMargin = ev.MarginBounds.Left;
float topMargin = ev.MarginBounds.Top;
String line=null;
//Work out the number of lines per page
//Use the MarginBounds on the event to do this
lpp = ev.MarginBounds.Height / printFont.GetHeight(ev.Graphics) ;
//Now iterate over the file printing out each line
//NOTE WELL: This assumes that a single line is not wider than the page width
//Check count first so that we don't read line that we won't print
while (count < lpp && ((line=streamToPrint.ReadLine()) != null)) {
yPos = topMargin + (count * printFont.GetHeight(ev.Graphics));
//Print Preview control will not work.
ev.Graphics.DrawString (line, printFont, Brushes.Black, leftMargin,
yPos, new StringFormat());
count++;
}
//If we have more lines then print another page
if (line != null)
ev.HasMorePages = true ;
else
ev.HasMorePages = false ;
}
}
Public Class TextFilePrintDocument
Inherits PrintDocument
Private printFont As Font
Private streamToPrint As StreamReader
Public Sub New(streamToPrint As StreamReader)
MyBase.New
Me.streamToPrint = streamToPrint
End Sub
'Override OnBeginPrint to set up the font we are going to use
Overrides Protected Sub OnBeginPrint(ev As PrintEventArgs)
MyBase.OnBeginPrint(ev)
printFont = new Font("Arial", 10)
End Sub
'Override the OnPrintPage to provide the printing logic for the document
Overrides Protected Sub OnPrintPage(ev As PrintPageEventArgs)
MyBase.OnPrintPage(ev)
Dim lpp As Single = 0
Dim yPos As Single = 0
Dim count As Integer = 0
Dim leftMargin As Single = ev.MarginBounds.Left
Dim topMargin As Single = ev.MarginBounds.Top
Dim line as String
'Work out the number of lines per page
'Use the MarginBounds on the event to do this
lpp = ev.MarginBounds.Height / printFont.GetHeight(ev.Graphics)
'Now iterate over the file printing out each line
'NOTE WELL: This assumes that a single line is not wider than the page width
'Check count first so that we don't read line that we won't print
line = streamToPrint.ReadLine()
While (count < lpp And line <> Nothing)
yPos = topMargin + (count * printFont.GetHeight(ev.Graphics))
ev.Graphics.DrawString(line, printFont, Brushes.Black, leftMargin, _
yPos, New StringFormat())
count = count + 1
If (count < lpp) Then
line = streamToPrint.ReadLine()
End If
End While
'If we have more lines then print another page
If (line <> Nothing) Then
ev.HasMorePages = True
Else
ev.HasMorePages = False
End If
End Sub
End Class
| ||
| C# | VB | |
查看并运行此示例。
[运行示例] | [查看源代码] |
第 3 步:允许用户选择打印机
在打印逻辑工作正常以后,下一步是允许用户使用 Windows"打印"对话框选择打印机。为此,创建 PrintDocument 并将其传递给 PrintDialog。
//Event fired when the user presses the print button
private void printButton_Click(object sender, EventArgs e) {
StreamReader streamToPrint = new StreamReader ("PrintMe.Txt");
try {
//Assumes the default printer
TextFilePrintDocument pd = new TextFilePrintDocument(streamToPrint);
PrintDialog dlg = new PrintDialog() ;
dlg.Document = pd;
DialogResult result = dlg.ShowDialog();
if (result == DialogResult.OK) {
pd.Print();
}
} finally {
streamToPrint.Close() ;
}
}
Private Sub printButton_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Try
Dim streamToPrint As StreamReader = New StreamReader("PrintMe.Txt")
Try
'Assumes the default printer
Dim pd As TextFilePrintDocument = New TextFilePrintDocument(streamToPrint)
Dim dlg As New PrintDialog()
dlg.Document = pd
Dim result As DialogResult = dlg.ShowDialog()
If (result = System.Windows.Forms.DialogResult.OK) Then
pd.Print()
End If
Finally
streamToPrint.Close()
End Try
Catch ex As Exception
MessageBox.Show("An error occurred printing the file - " + ex.Message)
End Try
End Sub
| ||
| C# | VB | |
查看并运行此示例。
[运行示例] | [查看源代码] |
第 4 步:允许用户选择页面设置
用户可以选择打印机并打印文档后,可以允许他们选择页面设置,如纸张方向或边距大小。为此,创建 PageSettings 实例并将其传递给 PageSetupDialog。
//Event fired when the user presses the page setup button
private void pageSetupButton_Click(object sender, EventArgs e) {
PageSetupDialog psDlg = new PageSetupDialog() ;
if (storedPageSettings == null) {
storedPageSettings = new PageSettings();
}
psDlg.PageSettings = storedPageSettings ;
psDlg.ShowDialog();
}
'Event fired when the user presses the page setup button
Private Sub pageSetupButton_Click(sender As object, e As System.EventArgs)
Try
Dim psDlg As New PageSetupDialog
If (storedPageSettings Is Nothing) Then
storedPageSettings = new PageSettings()
End If
psDlg.PageSettings = storedPageSettings
psDlg.ShowDialog
Catch ex As Exception
MessageBox.Show("An error occurred - " + ex.Message)
End Try
End Sub
| ||
| C# | VB | |
然后可在用户打印文档时使用此自定义 PageSettings 实例。
//Event fired when the user presses the print button
private void printButton_Click(object sender, EventArgs e) {
StreamReader streamToPrint = new StreamReader ("PrintMe.Txt");
try {
TextFilePrintDocument pd = new TextFilePrintDocument(streamToPrint);
if (storedPageSettings != null) {
pd.DefaultPageSettings = storedPageSettings ;
}
PrintDialog dlg = new PrintDialog() ;
dlg.Document = pd;
DialogResult result = dlg.ShowDialog();
if (result == DialogResult.OK) {
pd.Print();
}
} finally {
streamToPrint.Close() ;
}
}
'Event fired when the user presses the print button
Private Sub printButton_Click(sender As object, e As System.EventArgs)
Try
Dim streamToPrint As StreamReader = new StreamReader ("PrintMe.Txt")
Try
'Assumes the default printer
Dim pd As TextFilePrintDocument = new TextFilePrintDocument(streamToPrint)
If Not (storedPageSettings Is Nothing) Then
pd.DefaultPageSettings = storedPageSettings
End If
Dim dlg As New PrintDialog()
dlg.Document = pd
Dim result As DialogResult = dlg.ShowDialog()
If (result = System.Windows.Forms.DialogResult.OK) Then
pd.Print()
End If
Finally
streamToPrint.Close()
End Try
Catch ex As Exception
MessageBox.Show("An error occurred printing the file - " + ex.Message)
End Try
End Sub
| ||
| C# | VB | |
查看并运行此示例。
[运行示例] | [查看源代码] |
第 5 步:显示“打印预览”窗口
“打印预览”窗口使用户得以在打印他们的文档前预览该文档。可以通过创建 PrintDocument 并将其传递到 PrintPreview 对话框,将“打印预览”窗口添加到应用程序中。
//Event fired when the user presses the print preview button
private void printPreviewButton_Click(object sender, EventArgs e) {
StreamReader streamToPrint = new StreamReader ("PrintMe.Txt");
try {
TextFilePrintDocument pd = new TextFilePrintDocument(streamToPrint);
if (storedPageSettings != null) {
pd.DefaultPageSettings = storedPageSettings ;
}
PrintPreviewDialog dlg = new PrintPreviewDialog() ;
dlg.Document = pd;
dlg.ShowDialog();
} finally {
streamToPrint.Close() ;
}
}
'Event fired when the user presses the print preview button
Private Sub printPreviewButton_Click(sender As object, e As System.EventArgs)
Try
Dim streamToPrint As StreamReader = new StreamReader ("PrintMe.Txt")
Try
'Assumes the default printer
Dim pd As TextFilePrintDocument = new TextFilePrintDocument(streamToPrint)
If Not (storedPageSettings Is Nothing) Then
pd.DefaultPageSettings = storedPageSettings
End If
Dim dlg As New PrintPreviewDialog()
dlg.Document = pd
dlg.ShowDialog()
Finally
streamToPrint.Close()
End Try
Catch ex As Exception
MessageBox.Show("An error occurred - " + ex.Message)
End Try
End Sub
| ||
| C# | VB | |
查看并运行此示例。
[运行示例] | [查看源代码] |
将所有内容组合在一起
Windows 窗体示例包括一个名为 SimplePad 的示例,该示例显示如何生成一个打印正在编辑的文件的简单文本编辑器。
[运行示例] | [查看源代码] |