XTab's Blog

Ged Mead's Blog at vbCity

This blog hosted by:
http://blogs.vbcity.com      
  Home :: Syndication  :: Login

MarApril 2008May
SMTWTFS
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

Archives

Topics

Ramblings

VB.NET

Tuesday, April 08, 2008 #

Introduction
  Printing can often be a bit of a tricky task in .NET. Some things are more easily resolved than others though.

  I saw a post recently that raised a problem that seems to occur fairly regularly: You want to print a large chunk of text to the printer, but VB seems to want to print everything all on one long line - even when this means that a lot of the text will be truncated or "printed" invisibly into thin air!

  Fortunately, this is one of the cases where the solution is relatively easy. Essentially, what you do is set a rectangle whose width represents the width of your printed page (or any lesser width you prefer). You then pass this rectangle to the DrawString method and it will obediently print within those boundaries.

Solution
   Here's the basic solution:

Code Copy
  Imports System.Drawing.Printing

Public
Class frmPrint

    ' The document you will use to print on
    Dim DocPrint As PrintDocument

   ' Set font for printing
        Dim fnt As Font = New Font("Verdana", 12, FontStyle.Regular)

'  The printing is fired with a button click event
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        '  Print the textbox content

        DocPrint = New PrintDocument
        ' A handler for it
        AddHandler DocPrint.PrintPage, AddressOf PrintTheTextBox1

        ' Print the document
        DocPrint.Print()
    End Sub

  '  The procedure that does the printing
  Private Sub PrintTheTextBox1(ByVal sender As Object, ByVal e As PrintPageEventArgs)

        'Set a rectangle to bound the  printing
        Dim PrintRect As New RectangleF
        PrintRect.Width = 800
        PrintRect.Height = 1000

        ' Print the text from the TextBox:
        e.Graphics.DrawString(TextBox1.Text, fnt, Brushes.Black, PrintRect)

    End Sub


 

Yes, But.....
  That's OK as far as it goes, but it does suffer from one flaw. When you check your printed page you'll find that the text is stuffed right up at the top left of the paper and each line extends fully across to the very last few millimetres at the right hand side. Now, it may be that paper saving is high on your agenda, in which case you'll be happy. But generally you will probably want a layout that's a bit more generous with its whitespace.

   The trouble is that there isn't an overload that allows you to pass in the Rectangle and the start position for the printing. Is that going to stump us? Nah, of course not!

  If we go back to the Rectangle itself, there is a constructor overload that allows you to pass in the x and y values as well as the width and height. The x and y values will of course be used as the left and top points respectively of the rectangle as it is positioned on the printed page. So this variation will get the start position, the text line width and text block height all sorted:

Code Copy
Private Sub PrintTheTextBox2(ByVal sender As Object, ByVal e As PrintPageEventArgs)

        'Set a rectangle to bound the  printing
        Dim PrintRect As New RectangleF(30, 100, 750, 1000)
       '  Assign its Left, Top, Width and Height values

        ' Print the text from the TextBox:
        e.Graphics.DrawString(TextBox1.Text, fnt, Brushes.Black, PrintRect)

    End Sub

  While I was working on that, I remembered that the Rectangle has a useful little method named Offset (something you would normally use when drawing actual rectangles in a graphics based task). However, by using this method and adjusting the values that are passed so that the top left of the rectangle is shunted down and to the right, we can get nearer to the layout we desire. If you chose to use this alternative route, it would look like this:

Code Copy
Dim PrintRect As New RectangleF
        PrintRect.Width = 800
        PrintRect.Height = 1000
        PrintRect.Offset(25, 60)

Show Me The Width
  It probably won't have escaped your notice that I very conveniently just happened to know what width and height I needed for the text to span across the page. Many times you will have this information to hand, but if you don't, what do you do then? Answer: You calculate it by querying the PrintDocument's PageSettings, find the width, height and margins and use those. Here's the code:

Code Copy
   Private Sub PrintTheTextBox3(ByVal sender As Object, ByVal e As PrintPageEventArgs)

        'Set a rectangle to bound the  printing
        Dim PrintRect As New RectangleF

        With DocPrint.DefaultPageSettings
            PrintRect.Width = .PaperSize.Width - (.Margins.Left + .Margins.Right)

            PrintRect.Height = .PaperSize.Height

            PrintRect.Offset(.Margins.Left, .Margins.Top)
        End With


        ' Print the text from the TextBox:
        e.Graphics.DrawString(TextBox1.Text, fnt, Brushes.Black, PrintRect)

    End Sub

Summary 

 Although there are many more tweaks we could add to this approach, I think that the above will cover many common situations. If text trimming at the end of lines is something you need to refine to the nth degree then you should check out the StringFormat class in general and the StringTrimming enumeration in particular. There are several options available there.

  Don't forget of course that you may not need to hand code your printing processes at all. There is a free Power Pack available which will print the contents of a form with minimum effort on your part. This will often be all that you need, but if not then at least you now know how to package up a bundle of text and send it to the printer to be laid out in a way that suits your requirements.

posted @ 5:06 PM | Feedback (0)