Printing
Most of the programs described in earlier chapters display output on the computers screen.
Chapters 29 and 30 explain how to save output in files.
This chapter explains a third method for saving output: printing. Using these techniques, you
can print text, shapes, images just about anything you want.
Before you start a printing project, however, be warned that printing in C# isn’t
trivial. Its easy enough to display some text or a few lines in a printout, but
producing a complex formatted document can be a lot of work.
If you need to produce a nicely formatted resume, graph, or grid of values, you
should ask yourself whether there’s an easier way. For example, Microsoft Word
is great at producing nicely formatted text documents, and Microsoft Excel
does a wonderful job of making charts and graphs. You can certainly generate
these sorts of printouts using C#, but it may be a lot faster if you use another
tool such as Word or Excel.
Note that this isn’t the only way to print with C# code. For example, a C# pro-
gram that uses Windows Presentation Foundation (WPF) can build WPF docu-
ments for later printing, or it can use the WPF printing techniques described in
Lesson 41. A program can also use a reporting tool such as Crystal Reports.
BASIC PRINTING
The PrintDocument component sits at the center of the printing process. To print, a program
creates an instance of this class either at design time or at run time. It adds event handlers to
catch the objects events and then lets the object do its thing. As the object generates pieces of
the printout, it raises events to let the program supply graphics for it to print.
31
596906c31.indd 359 4/7/10 12:34:29 PM
360
LESSON 31 Printing
The PrintDocument object raises four key events:
BeginPrint
Raised when the object is about to start printing. The program should do
whatever it must to get ready to print.
QueryPageSettings
Raised when the object is about to start printing a page. The pro-
gram can modify the next page’s settings. For example, it might adjust the margins so even
pages have bigger margins on the left than odd pages or vice versa to allow for a staple in a
double-sided document.
PrintPage
Raised when the object needs to generate contents for a page. This is where
the program does its drawing. It should set the event handler’s
e.HasMorePages value to
false if this is the last page.
EndPrint
Raised after the object has finished printing. The program can perform any nec-
essary clean up here.
The
BeginPrint, QueryPageSettings, and EndPrint event handlers are optional. For simple
printouts, you may only need the
PrintPage event handler.
The
PrintPage event handler gives you a parameter named e of type PrintPageEventArgs. This
object contains the
HasMorePages parameter that you use to tell the PrintDocument whether this is the
last page, a
Graphics object that you use to draw the page’s contents, a PageBounds property that tells
you how big the page is, and a
MarginBounds property that tells you where the page’s margins are.
Drawing Shapes
The easiest way to generate a printout
using the
PrintDocument object is to
place the object on a form and give the
object a
PrintPage event handler to
generate the pages. When you’re ready
to print, simply call the object’s
Print
method to send the printout to the
default printer. As it builds the pages,
the
PrintDocument raises its PrintPage
event to find out what to draw.
Once you’ve done this much, it’s prac-
tically trivial to add a print preview
capability to the program. Add a
PrintPreviewDialog object to the form
and set its
Document property to the
PrintDocument object that you already
created. To display a print preview, simply call the dialog’s
ShowDialog method. The dialog uses the
associated
PrintDocument object to generate the necessary preview and displays the result.
Figure 31-1 shows the PrintShapes example program (available as part of this lesson’s code down-
load) displaying a four-page print preview that contains a triangle, rectangle, ellipse, and diamond.
FIGURE 311
596906c31.indd 360 4/7/10 12:34:30 PM
Basic Printing
361
The following code shows the program’s PrintPage event handler:
// The number of the next page.
private int nextPageNum = 0;
// Print a page.
private void shapesPrintDocument_PrintPage(object sender,
System.Drawing.Printing.PrintPageEventArgs e)
{
// These are used to draw the triangle and diamond.
float xmid = (e.MarginBounds.Left + e.MarginBounds.Right) / 2;
float ymid = (e.MarginBounds.Top + e.MarginBounds.Bottom) / 2;
// See which page this is.
switch (nextPageNum)
{
case 0: // Draw a triangle.
PointF[] trianglePoints =
{
new PointF(xmid, e.MarginBounds.Top),
new PointF(e.MarginBounds.Left, e.MarginBounds.Bottom),
new PointF(e.MarginBounds.Right, e.MarginBounds.Bottom),
};
using (Pen pen = new Pen(Color.Red, 10))
{
e.Graphics.DrawPolygon(pen, trianglePoints);
}
break;
case 1: // Draw a rectangle.
using (Pen pen = new Pen(Color.Blue, 10))
{
e.Graphics.DrawRectangle(pen, e.MarginBounds);
}
break;
case 2: // Draw an ellipse.
using (Pen pen = new Pen(Color.Green, 10))
{
e.Graphics.DrawEllipse(pen, e.MarginBounds);
}
break;
case 3: // Draw a diamond.
PointF[] diamondPoints =
{
new PointF(xmid, e.MarginBounds.Top),
new PointF(e.MarginBounds.Right, ymid),
new PointF(xmid, e.MarginBounds.Bottom),
new PointF(e.MarginBounds.Left, ymid),
};
using (Pen pen = new Pen(Color.Black, 10))
{
e.Graphics.DrawPolygon(pen, diamondPoints);
}
break;
}
nextPageNum += 1;
596906c31.indd 361 4/7/10 12:34:30 PM
362
LESSON 31 Printing
if (nextPageNum > 3)
{
// This is the last page. Start over if we print again.
e.HasMorePages = false;
nextPageNum = 0;
}
else
{
// We have more pages.
e.HasMorePages = true;
}
}
The nextPageNum variable stores the number of the next page for the program to print.
The event handler uses a
switch statement to decide which shape it should draw. Depending on
the page number, it uses the
e.Graphics object’s DrawPolygon, DrawRectangle, or DrawEllipse
method to draw different shapes.
The code uses different
Pen objects to draw the various shapes. For example, it draws the triangle
with a 10-pixel wide red pen. The using statements automatically dispose of the
Pens resources
when the program is done with them.
After it draws the current page’s shape, the program increments
nextPageNum. If the new page number
is greater than 3, the program has finished drawing all of the pages (there are 4 of them, numbered
starting with 0) so it sets
e.HasMorePages to false. It also resets nextPageNum to 0 so the program
starts over the next time you click one of the buttons.
If the next page number is not greater than 3, the program has more pages to print so it sets
e.HasMorePages to true.
The following code shows how the program displays print previews and generates printouts:
// Display a print preview.
private void previewButton_Click(object sender, EventArgs e)
{
shapesPrintPreviewDialog.ShowDialog();
}
// Print.
private void printButton_Click(object sender, EventArgs e)
{
shapesPrintDocument.Print();
}
Unfortunately there isn’t room in this lesson to really get into the drawing
routines that you use to generate fancier printouts. See Lesson 39 for more
details. For a more complete introduction to graphics programming in C#,
see my PDF-format Wrox Blox C# Graphics Programming available at
www.wrox.com/WileyCDA/WroxTitle/productCd-0470343494.html.
596906c31.indd 362 4/7/10 12:34:30 PM
Basic Printing
363
Drawing Text
The PrintShapes program described in the preceding section demonstrates the basic techniques you
need to print. It uses a
PrintPage event handler to draw different shapes on four pages of a printout.
You can print text in much the same way you print shapes. The only real difference is that to draw
text you use the
e.Graphics object’s DrawString method instead of one of the other Graphics
methods such as
DrawPolygon or DrawEllipse.
Example program PrintText (available as part of this lesson’s code download) uses the following
code to print a series of names on a single page:
// Print some text on one page.
private void textPrintDocument_PrintPage(object sender,
System.Drawing.Printing.PrintPageEventArgs e)
{
// Make a font to use.
using (Font font = new Font(“Times New Roman”, 20))
{
// Get the coordinates for the first line.
int x = e.MarginBounds.Left;
int y = e.MarginBounds.Top;
// Print some text.
string[] names =
{
“Arsenal”, “Burnley”, “Chelsea”, “Liverpool”,
“Man City”, “Portsmouth”, “Tottenham”, “Wigan”,
};
foreach (string name in names)
{
// Print the name.
e.Graphics.DrawString(name, font, Brushes.Black, x, y);
// Move down for the next line.
y += 30;
}
}
// We only have one page.
e.HasMorePages = false;
}
The program first creates a large font to use when drawing text. It uses a using statement to dispose
of the font’s resources when the program is done with it.
Next the code sets variables
x and y to the coordinates where the first name should appear. In this
example, the program displays the first line in the upper-left corner of the page’s margin bounds.
The program then loops through an array of names. For each name, the program uses the
e.Graphics object’s DrawString method to draw the name. It then adds 30 to the variable y so
the next name is printed farther down the page.
596906c31.indd 363 4/7/10 12:34:30 PM
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.116.49.243