# Printing with PrintDocument in .Net

In recently needed to print labels/tickets on a series of [ZEBRA](http://www.zebra.com/) printers.

[![image](http://www.mythicalmanmoth.com/wp-content/uploads/2009/10/image-thumb7.png "image")](http://www.mythicalmanmoth.com/wp-content/uploads/2009/10/image7.png)

This required some very specific sized labels/tickets. At first I designed everything in Crystal Reports, and everything previewed perfectly,until… I actually had to print it to the printer. The printer driver plays a very specific role, and can cause some serious headaches.

Eventually I resorted to using the .Net PrintDocument component, that allows you to specify the paper size and print to the printer on a lower level than Crystal Reports. This worked very nicely for one label/ticket, but I wanted to print a range of labels/tickets.

The Printdocument has a very strange way of processing the print command. In it’s PrintPage event, you set the e.HasMorePages property if you want to print more than one page, and the PrintPage method loops until e.HasMorePages is false. Talk about a messing with your train of thought.

What I needed was a way to say to the PrintDocument that it should print the next page, and then pass my ticket object with the next ticket’s information. Easier said than done. Fortunately, I stumbled onto this [forum discussion.](http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2031202&amp;SiteID=1) This code creates a custom class that inherits from the PrintDocument and give you a nifty .NextPage sub. This let’s the PrintDocument know that you’re moving onto the next page. I’m reposting it here for your convenience.

Printers sure are a lot of fun to try and figure out…depends on your opinion of fun ![🙂](https://cdn.hashnode.com/res/hashnode/image/upload/v1664178436081/ulxYjAhX2.png)

**Class code:**

Imports System.Threading

Imports System.Drawing.Printing

Public Class PrintDoc

    Inherits PrintDocument

    Private W1, W2 As EventWaitHandle

    Private PagesPrinted As Int32

    Public Event PrintPages(ByVal Sender As Object, ByRef e As System.Drawing.Printing.PrintPageEventArgs)

    Private T As Thread

    Private eRef As System.Drawing.Printing.PrintPageEventArgs

    Protected Overrides Sub OnPrintPage(ByVal e As System.Drawing.Printing.PrintPageEventArgs)

        eRef = e

        If PagesPrinted = 0 Then T.Start() Else W2.Set()

        PagesPrinted += 1

        W1.WaitOne()

    End Sub

    Private Sub PrintDoc\_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles Me.BeginPrint

        W1 = New EventWaitHandle(False, EventResetMode.AutoReset)

        W2 = New EventWaitHandle(False, EventResetMode.AutoReset)

        T = New Thread(AddressOf RaisePrintPages)

        PagesPrinted = 0

    End Sub

    Public Sub NextPage()

        eRef.HasMorePages = True

        W1.Set() : W2.WaitOne()

    End Sub

    Private Sub RaisePrintPages()

        RaiseEvent PrintPages(Me, eRef)

        W1.Set()

    End Sub

    Private Sub PrintDoc\_EndPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles Me.EndPrint

        W1.Close() : W2.Close()

    End Sub

End Class

**Code Implementation:**

Private Sub PrintDoc1\_PrintPages(ByVal Sender As Object, ByRef e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDoc1.PrintPages

    e.Graphics.DrawString("Hello", New Font("Arial", 12, FontStyle.Regular), Brushes.Black, 100, 100)

    PrintDoc1.NextPage()

    e.Graphics.DrawString("Hello Again", New Font("Arial", 12, FontStyle.Regular), Brushes.Black, 100, 100)

End Sub
