How to: Print in Windows Forms Using Print Preview
It is very common in Windows Forms programming to offer print preview in addition to printing services. An easy way to add print preview services to your application is to use a PrintPreviewDialog control in combination with the PrintPage event-handling logic for printing a file.
To preview a text document with a PrintPreviewDialog control
Add a PrintPreviewDialog, PrintDocument, and two strings to your form.
Private printPreviewDialog1 As New PrintPreviewDialog() Private WithEvents printDocument1 As New PrintDocument() ' Declare a string to hold the entire document contents. Private documentContents As String ' Declare a variable to hold the portion of the document that ' is not printed. Private stringToPrint As String
private PrintPreviewDialog printPreviewDialog1 = new PrintPreviewDialog(); private PrintDocument printDocument1 = new PrintDocument(); // Declare a string to hold the entire document contents. private string documentContents; // Declare a variable to hold the portion of the document that // is not printed. private string stringToPrint;
Set the DocumentName property to the document you wish to print, and open and read the document's contents to the string you added previously.
Private Sub ReadDocument() Dim docName As String = "testPage.txt" Dim docPath As String = "c:\" printDocument1.DocumentName = docName Dim stream As New FileStream(docPath + docName, FileMode.Open) Try Dim reader As New StreamReader(stream) Try documentContents = reader.ReadToEnd() Finally reader.Dispose() End Try Finally stream.Dispose() End Try stringToPrint = documentContents End Sub
private void ReadDocument() { string docName = "testPage.txt"; string docPath = @"c:\"; printDocument1.DocumentName = docName; using (FileStream stream = new FileStream(docPath + docName, FileMode.Open)) using (StreamReader reader = new StreamReader(stream)) { documentContents = reader.ReadToEnd(); } stringToPrint = documentContents; }
As you would for printing the document, in the PrintPage event handler, use the Graphics property of the PrintPageEventArgs class and the file contents to calculate lines per page and render the document's contents. After each page is drawn, check to see if it is the last page, and set the HasMorePages property of the PrintPageEventArgs accordingly. The PrintPage event is raised until HasMorePages is false. When the document has finished rendering, reset the string to be rendered. Also, make sure the PrintPage event is associated with its event-handling method.
Note
You may have already completed steps 2 and 3 if you have implemented printing in your application.
In the following code example, the event handler is used to print the "testPage.txt" file in the same font used on the form.
Sub printDocument1_PrintPage(ByVal sender As Object, _ ByVal e As PrintPageEventArgs) Handles printDocument1.PrintPage Dim charactersOnPage As Integer = 0 Dim linesPerPage As Integer = 0 ' Sets the value of charactersOnPage to the number of characters ' of stringToPrint that will fit within the bounds of the page. e.Graphics.MeasureString(stringToPrint, Me.Font, e.MarginBounds.Size, _ StringFormat.GenericTypographic, charactersOnPage, linesPerPage) ' Draws the string within the bounds of the page. e.Graphics.DrawString(stringToPrint, Me.Font, Brushes.Black, _ e.MarginBounds, StringFormat.GenericTypographic) ' Remove the portion of the string that has been printed. stringToPrint = stringToPrint.Substring(charactersOnPage) ' Check to see if more pages are to be printed. e.HasMorePages = stringToPrint.Length > 0 ' If there are no more pages, reset the string to be printed. If Not e.HasMorePages Then stringToPrint = documentContents End If End Sub
void printDocument1_PrintPage(object sender, PrintPageEventArgs e) { int charactersOnPage = 0; int linesPerPage = 0; // Sets the value of charactersOnPage to the number of characters // of stringToPrint that will fit within the bounds of the page. e.Graphics.MeasureString(stringToPrint, this.Font, e.MarginBounds.Size, StringFormat.GenericTypographic, out charactersOnPage, out linesPerPage); // Draws the string within the bounds of the page. e.Graphics.DrawString(stringToPrint, this.Font, Brushes.Black, e.MarginBounds, StringFormat.GenericTypographic); // Remove the portion of the string that has been printed. stringToPrint = stringToPrint.Substring(charactersOnPage); // Check to see if more pages are to be printed. e.HasMorePages = (stringToPrint.Length > 0); // If there are no more pages, reset the string to be printed. if (!e.HasMorePages) stringToPrint = documentContents; }
Set the Document property of the PrintPreviewDialog control to the PrintDocument component on the form.
printPreviewDialog1.Document = printDocument1
printPreviewDialog1.Document = printDocument1;
Call the ShowDialog method on the PrintPreviewDialog control. You would typically call ShowDialog from the Click event-handling method of a button. Calling ShowDialog raises the PrintPage event and renders the output to the PrintPreviewDialog control. When the user clicks the print icon on the dialog, the PrintPage event is raised again, sending the output to the printer instead of the preview dialog. This is why the string is reset at the end of the rendering process in step 3.
The following code example shows the Click event-handling method for a button on the form. This event-handling method calls the methods to read the document and show the print preview dialog.
Private Sub printPreviewButton_Click(ByVal sender As Object, _ ByVal e As EventArgs) Handles printPreviewButton.Click ReadDocument() printPreviewDialog1.Document = printDocument1 printPreviewDialog1.ShowDialog() End Sub
private void printPreviewButton_Click(object sender, EventArgs e) { ReadDocument(); printPreviewDialog1.Document = printDocument1; printPreviewDialog1.ShowDialog(); }
Example
Imports System
Imports System.Drawing
Imports System.IO
Imports System.Drawing.Printing
Imports System.Windows.Forms
Class Form1
Inherits Form
Private WithEvents printPreviewButton As Button
Private printPreviewDialog1 As New PrintPreviewDialog()
Private WithEvents printDocument1 As New PrintDocument()
' Declare a string to hold the entire document contents.
Private documentContents As String
' Declare a variable to hold the portion of the document that
' is not printed.
Private stringToPrint As String
Public Sub New()
Me.printPreviewButton = New System.Windows.Forms.Button()
Me.printPreviewButton.Location = New System.Drawing.Point(12, 12)
Me.printPreviewButton.Size = New System.Drawing.Size(125, 23)
Me.printPreviewButton.Text = "Print Preview"
Me.ClientSize = New System.Drawing.Size(292, 266)
Me.Controls.Add(Me.printPreviewButton)
End Sub
Private Sub ReadDocument()
Dim docName As String = "testPage.txt"
Dim docPath As String = "c:\"
printDocument1.DocumentName = docName
Dim stream As New FileStream(docPath + docName, FileMode.Open)
Try
Dim reader As New StreamReader(stream)
Try
documentContents = reader.ReadToEnd()
Finally
reader.Dispose()
End Try
Finally
stream.Dispose()
End Try
stringToPrint = documentContents
End Sub
Sub printDocument1_PrintPage(ByVal sender As Object, _
ByVal e As PrintPageEventArgs) Handles printDocument1.PrintPage
Dim charactersOnPage As Integer = 0
Dim linesPerPage As Integer = 0
' Sets the value of charactersOnPage to the number of characters
' of stringToPrint that will fit within the bounds of the page.
e.Graphics.MeasureString(stringToPrint, Me.Font, e.MarginBounds.Size, _
StringFormat.GenericTypographic, charactersOnPage, linesPerPage)
' Draws the string within the bounds of the page.
e.Graphics.DrawString(stringToPrint, Me.Font, Brushes.Black, _
e.MarginBounds, StringFormat.GenericTypographic)
' Remove the portion of the string that has been printed.
stringToPrint = stringToPrint.Substring(charactersOnPage)
' Check to see if more pages are to be printed.
e.HasMorePages = stringToPrint.Length > 0
' If there are no more pages, reset the string to be printed.
If Not e.HasMorePages Then
stringToPrint = documentContents
End If
End Sub
Private Sub printPreviewButton_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles printPreviewButton.Click
ReadDocument()
printPreviewDialog1.Document = printDocument1
printPreviewDialog1.ShowDialog()
End Sub
<STAThread()> _
Shared Sub Main()
Application.EnableVisualStyles()
Application.SetCompatibleTextRenderingDefault(False)
Application.Run(New Form1())
End Sub
End Class
using System;
using System.Drawing;
using System.IO;
using System.Drawing.Printing;
using System.Windows.Forms;
namespace PrintPreviewApp
{
public partial class Form1 : Form
{
private Button printPreviewButton;
private PrintPreviewDialog printPreviewDialog1 = new PrintPreviewDialog();
private PrintDocument printDocument1 = new PrintDocument();
// Declare a string to hold the entire document contents.
private string documentContents;
// Declare a variable to hold the portion of the document that
// is not printed.
private string stringToPrint;
public Form1()
{
this.printPreviewButton = new System.Windows.Forms.Button();
this.printPreviewButton.Location = new System.Drawing.Point(12, 12);
this.printPreviewButton.Size = new System.Drawing.Size(125, 23);
this.printPreviewButton.Text = "Print Preview";
this.printPreviewButton.Click += new System.EventHandler(this.printPreviewButton_Click);
this.ClientSize = new System.Drawing.Size(292, 266);
this.Controls.Add(this.printPreviewButton);
printDocument1.PrintPage +=
new PrintPageEventHandler(printDocument1_PrintPage);
}
private void ReadDocument()
{
string docName = "testPage.txt";
string docPath = @"c:\";
printDocument1.DocumentName = docName;
using (FileStream stream = new FileStream(docPath + docName, FileMode.Open))
using (StreamReader reader = new StreamReader(stream))
{
documentContents = reader.ReadToEnd();
}
stringToPrint = documentContents;
}
void printDocument1_PrintPage(object sender, PrintPageEventArgs e)
{
int charactersOnPage = 0;
int linesPerPage = 0;
// Sets the value of charactersOnPage to the number of characters
// of stringToPrint that will fit within the bounds of the page.
e.Graphics.MeasureString(stringToPrint, this.Font,
e.MarginBounds.Size, StringFormat.GenericTypographic,
out charactersOnPage, out linesPerPage);
// Draws the string within the bounds of the page.
e.Graphics.DrawString(stringToPrint, this.Font, Brushes.Black,
e.MarginBounds, StringFormat.GenericTypographic);
// Remove the portion of the string that has been printed.
stringToPrint = stringToPrint.Substring(charactersOnPage);
// Check to see if more pages are to be printed.
e.HasMorePages = (stringToPrint.Length > 0);
// If there are no more pages, reset the string to be printed.
if (!e.HasMorePages)
stringToPrint = documentContents;
}
private void printPreviewButton_Click(object sender, EventArgs e)
{
ReadDocument();
printPreviewDialog1.Document = printDocument1;
printPreviewDialog1.ShowDialog();
}
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
Compiling the Code
This example requires:
References to the System, System.Windows.Forms, System.Drawing assemblies.
For information about building this example from the command line for Visual Basic or Visual C#, see Building from the Command Line (Visual Basic) or Command-line Building With csc.exe. You can also build this example in Visual Studio by pasting the code into a new project. For more information, see How to: Compile and Run a Complete Windows Forms Code Example Using Visual Studio and How to: Compile and Run a Complete Windows Forms Code Example Using Visual Studio and How to: Compile and Run a Complete Windows Forms Code Example Using Visual Studio and How to: Compile and Run a Complete Windows Forms Code Example Using Visual Studio.
See Also
Tasks
How to: Print a Multi-Page Text File in Windows Forms
Concepts
More Secure Printing in Windows Forms