Printing Multiple Pages in C#

So far we have discussed printing only an image or a single-page file. Printing multipage files is another important part of printing functionality that developers may need to implement when writing printer applications. Unfortunately, the .NET Framework does not keep track of page numbers for you, but it provides enough support for you to keep track of the current page, the total number of pates, the last page, and a particular page number. Basically, when printing a multipage document, you need to find out the total number of pages and print them from first to last. You can also specify a particular page number. If you are using the default Windows printing dialog, then you don't have to worry about it because you can specify the pages in the dialog, and the framework takes care of this for you.

To demonstrate how to do this, our next programs produces a useful printout showing all the fonts installed on your computer. This program is a useful tool for demonstrating the calculation of how many pages to print when you're using graphical commands to print.

We will use the PrintPreview facility to display the output in case you don't have access to a printer and how far down the page we are. If we're going to go over the end of the page, we drop out of the pd_PrintPage event handler and set ev.HasMorePages to true to indicate that we have another page to print.

To see this functionality in action, let's create a Windows application and add a menu with three menu items and a RichTextBox control to the form. The final form is shown in Figure 11.24.


FIGURE 11.24: A form for printing multiple pages

The Display Fonts menu display available fonts on the machine. Before we add code to this menu, we add the following variables:

        private int fontcount;
        private int fontposition = 1;
        private float ypos = 1;
        private PrintPreviewDialog previewDlg = null;

The code for the Display Fonts menu click is given in Listing 11.44. Here we read installed fonts on the system and display them in the rich text box. We use InstalledFontCollection to read all installed fonts on a machine. Then we use the InstalledFontCollection.Families property and make a loop to read all the font families. We also check if these families support different styles, including regular, bold, italic, and underline, and wee add some text to the rich text box with the current font.

LISTING 11.44: Displaying fonts

private void DisplayFonts_Click1 (object sender, Sytem.EventArgs e)

//Create InstalledFontCollection objects
InstalledFontCollection ifc =
new InstalledFontCollection();
//Get font families
FontFamily[] ffs = ifc.Families;
Font f;
//Make sure rich text box is empty
//Read font families one by one,
//set font to some text,
//and add text to the text box
foreach (FontFamily ff in ffs)
if (ff.IsStyleAvailable (FontStyle.Regular))
f = new Font (ff.GetName(1),12, FontStyle.Regular);
else if (ff.IsStyleAvailable (FontStyle.Bold))
f = new Font (ff.GetName (1),12, FontStyle.Bold);
else if (ff.IsStyleAvailable (FontStyle.Italic))
f = new Font (ff.GetName(1),12, FontStyle.Italic);
f=new Font(ff.GetName(1),12, FontStyle.Underline);
richTextBox1.SelectionFont = f;
richTextBox1.AppendText(ff.GetName(1)+ "\r\n");

The code for the Print Preview and Print menu items is given in Listing 11.45. This code should look familiar to you. We simply create PrintDocument and PrintPreviewDialog objects, set their properties, add a print-page event handler, and call the Print and Show methods.

LISTING 11.45: The Print Preview and Print menu items

        private void PrintPreviewMenuClick(object sender, System.EventArgs e)
            //Create a PrintPreviewDialog object
            previewDlg = new PrintPreviewDialog();
            //Create a PrintDocument object
            PrintDocument pd = new PrintDocument();
            //Add print-page event handler
            pd.PrintPage +=
            new PrintPageEventHanlder(pd_PrintPage);
            //Set Document property of PrintPreviewDialog
            previewDlg.Document = pd;
            //Display dialog

        private void PrintMenuClick(object sender, System.EventArgs e)
            //Create a PrintPreviewDialog object
            previewDlg = new PrintPreviewDialog();
            //Create a PrintDocument object
            PrintDocument pd = new PrintDocument();
            //Add print-page event handler
            pd.PrintPage +=
            new PrintPageEventHandler(pd_PrintPage);

The print-page event handler, pd_PrintPage, is given in Listing 11.46. We print fonts using DrawString, and we set PrintPageEventArgs.HasMorePages to true. To make sure the text fits, we increase the y-position by 60 units.

LISTING 11.46: The print-page event handler

        public void pd_PrintPage(object sender, PrintPageEventArgs ev)
            ypos = 1;
            float pageheight = ev.MarginBounds.Height;
            //Create a Graphics object
            Graphics g = ev.Graphics;
            //Get installed fonts
            InstalledFontCollection ifc =
            new InstalledFontCollection();
            //Get font families
            FontFamily[] ffs = ifc.Families;
            //Draw string on the paper
            while (ypos + 60 < pageheight &&
            fontposition < ffs.GetLength(0))
                //Get the font name
                Font f =
                new Font(ffs[fontposition].GetName(0), 25);
                //Draw string
                g.DrawString(ffs[fontposition].GetName(0), f,
                new SolidBrush(Color.Black), 1, ypos);
                fontposition = fontposition + 1;
                ypos = ypos + 60;
            if (fontposition < ffs.GetLength(0))
                //Has more pages??
                ev.HasMorePages = true;

That's it. If we run the program, the Print menu prints multiple pages, and the Print Preview menu shows the print preview on two pages (see Figure 11.25).

As you can see, it's pretty easy to create multipage report generators. Now you can use the print option to print documents with multiple pages.

The DocumentName Property
If you want to display the name of the document you're printing, you can use the DocumentName property of the PrintDocument object:
 pd.DocumentName ="A Text Document";
The new result is shown in Figure 11.26.
We have seen that using the DocumentPrintPreview class is fairly straightforward. In reality, all that's happening is that this control is passed a graphics class representing each page in a printout.
 FIGURE 11.25: Print preview of multiple pages
 FIGURE 11.26: Setting a document name



Build smarter apps with Machine Learning, Bots, Cognitive Services - Start free.

Start Learning Now