Click here to Skip to main content
15,120,739 members
Articles / Programming Languages / Visual Basic
Article
Posted 7 Jul 2012

Stats

43.4K views
2.1K downloads
27 bookmarked

A Simple TextPrinter

Rate me:
Please Sign up or sign in to vote.
4.91/5 (7 votes)
26 Jul 2012CPOL3 min read
A routine to print out text, images and lines (including complete text files)

Image 1

Note: The printout has been sent to a PDF-Printer to generate this sample.

Introduction

This routine allows to print out text, horizontal lines and images. It provides properties to specify the common used page settings (size, orientation, margins, etc.) and methods to set the text, lines and images plus the related formatting options (i.e., font, color). It uses internally the PrintDocument (Namespace: System.Drawing.Printing) and the StandardPrintController to generate the printouts. The StandardPrintController is further used to hide the default PrinterDialog and to print directly to the user's standard printer.

Background

Often, it is required to have a simple routine that prints complete text files or application messages and handles more than one page. Furthemore, it should be easy enough to set the common used page settings and to use standard formattings for the output. It should set internally the correct x and y drawing positions while the user provides only the printing objects (plus optional object related options). To meet all these requirements, I decided to write this class.

Using the Code

To print out your content, you just have to create a new instance of TextPrinter:

VB
Using prt As New TextPrinter(Printing.PaperKind.Letter)
    With prt
        With .Header1stPage
            .TextLeft = "Printed by: " & Environment.UserName
            .TextRight = "Page: [PAGE]" & vbCrLf & Now.ToString
        End With
        .Landscape = True
    End With
    '... further code
End Using

Additionally, you can set the following properties:

  • DefaultFont: The default printing font if you do not specify a font for the printing text
  • DocumentName: The document name used for the print queue and print prepare dialog
  • Footer1stPage: The footer shown on the 1st page (including formatting - i.e., font, color)
  • FooterPage: The footer shown on all other pages excepting the 1st one (including formatting - i.e., font, color)
  • Header1stPage: The header shown on the 1st page (including formatting - i.e., font, color)
  • HeaderPage: The header shown on all other pages excepting the 1st one (including formatting - i.e., font, color)
  • Landscape: Defines the used page orientation
  • PaperKind: The used paper kind - i.e., A4, Letter, etc.
  • TabCharWidth: The number of space character which replaces the tab character within the text (default: 4).

For the page header and footer, you can set an individual text for the left, middle and/or right position. [PAGE] is an auto-filled text variable (used in header/footer only) that shows the number of the page.

In the next step, you define the object that should be printed. In this case, a text from an external file via method SetText. You can choose the used font, forecolor and/or horizontal alignment as optional parameters:

VB
.SetText(My.Computer.FileSystem.ReadAllText(Application.StartupPath & "\print.xml", _
    System.Text.Encoding.Default), New Font("Courier New", 10), Color.Blue)

To print a horizontal line, you can define the line color, width and the horizontal alignment in method SetLine. In case you provide a width value <=1, the width will be interpreted as prozentual value. That means a value of 0.5 are 50% of the available page width:

VB
.SetLine(Color.Red)
.SetLine(Color.Blue, 0.5, HorizontalAlignment.Center)

An image can be printed via SetImage. As optional parameters, you can define the horiziontal alignment and the image size. In case the image size is greater than the page size, the image will automatically be resized to the page size:

VB
.SetImage(My.Resources.IMG_3392, HorizontalAlignment.Center)

The following code generates the above sample document. It uses the methods: SetLine, SetText, SetImage, and Print to create the printout. Alternatively, you can use the method: ShowPreview to show a PrinterPrintPreview and to print out the document directly from that preview:

VB
'read an external xml file as sample text file
Dim fileContent As String = String.Empty
Using file As New IO.StreamReader(Application.StartupPath & "\print.xml", True)
    fileContent = file.ReadToEnd
End Using

'create new instance and set paper size to A4
Using prt As New TextPrinter(PaperKind.A4)
    With prt
        'set header for the 1st page
        With .Header1stPage
            .TextLeft = "Printed by: " & Environment.UserName
            .TextRight = "Page: [PAGE]" & vbCrLf & Now.ToString
        End With
        'set footer for the 1st page
        With .Footer1stPage
            .TextCenter = "FOR INTERNAL USE ONLY!"
            .ColorCenter = Color.Red
        End With
        'for all other pages we are using a different header and footer:
        With .HeaderPage
            .TextRight = "Page: [PAGE]" & vbCrLf & Now.ToString
        End With
        With .FooterPage
            .TextCenter = "FOR INTERNAL USE ONLY!"
            .ColorCenter = Color.Red
            .TextLeft = "Application:" & vbCrLf & Assembly.GetExecutingAssembly.Location
        End With
        .DefaultFont = New Font("Tahoma", 10)

        'set the objects those will be printed
        .SetLine() 'no parameters specified: color black is used
        .SetText("START OF PRINTING.", New Font(.DefaultFont, FontStyle.Bold))
        .SetLine()
        .SetText(fileContent, New Font("Courier New", 10), Color.Blue)
        .SetLine()
        .SetText(vbCrLf & vbCrLf & "Now we are printing an image (taken in Nassfeld [Austria]:", _
                 New Font(.DefaultFont, FontStyle.Italic))
        .SetImage(My.Resources.IMG_3392, HorizontalAlignment.Center)
        .SetText("END OF PRINTING.", New Font(.DefaultFont, FontStyle.Bold))
        .SetLine()

        'print or show preview instead
        If isPreview Then
            'Show preview
            .ShowPreview(Me)
        Else
            'Prints directly:
            .Print()
        End If
    End With
End Using

That's all!

Points of Interest (or a Deeper View)

All drawings are done in class TextPrinter. The most important methods are _printPage (it handles the headers and footers plus the printing objects) and _printCharacters.

_printCharacters is used to measure the text for the available drawing size and returns the number of characters that were printed:

VB
Private Function _printCharacters(ByVal g As Graphics, ByVal text As String, _
        ByVal font As Font, ByVal align As HorizontalAlignment, _
        ByVal forecolor As Color, ByRef r As Rectangle) As Integer
    Dim chrFitted As Integer
    Using sf As New StringFormat
        With sf
            If text.Contains(vbTab) Then .FormatFlags = StringFormatFlags.MeasureTrailingSpaces
            'set the horizontal text alignment
            If align = HorizontalAlignment.Center Then
                .Alignment = StringAlignment.Center
            ElseIf align = HorizontalAlignment.Right Then
                .Alignment = StringAlignment.Far
            End If
        End With

        'get size of printable text
        Dim sz As SizeF = g.MeasureString(text, font, New Size(r.Width, r.Height - font.Height), _
                          sf, chrFitted, 0)
        With g
            Using b As New SolidBrush(forecolor)
                'draw characters those are fitting the rectangle
                .DrawString(Left(text, chrFitted), font, b, r, sf)
            End Using
        End With
        'reduce the rectangle by drawn characters
        r.Y += sz.Height
        r.Height -= sz.Height
    End Using

    'return the drawn number of characters
    Return chrFitted
End Function

History

  • 1.0.0.0 - Initial post
  • 1.0.0.1 - Small changes (Disposal of fonts and images; method _print uses the printer default pagesize if provided paperkind is unsupported)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Daniel Leykauf
Business Analyst
Austria Austria
I am working as Business Analyst and Development Specialist for an international bank since 1993.

Comments and Discussions

 
SuggestionThank you! Pin
Thomas Karlson10-Oct-12 12:00
MemberThomas Karlson10-Oct-12 12:00 
QuestionMy 5 Pin
rspercy6511-Jul-12 13:23
Memberrspercy6511-Jul-12 13:23 
GeneralMy vote of 5 Pin
rctaubert9-Jul-12 5:02
Memberrctaubert9-Jul-12 5:02 
QuestionWhy hardwire a paper size into your code? Pin
rctaubert8-Jul-12 13:23
Memberrctaubert8-Jul-12 13:23 
AnswerRe: Why hardwire a paper size into your code? Pin
Daniel Leykauf8-Jul-12 14:01
MemberDaniel Leykauf8-Jul-12 14:01 
GeneralRe: Why hardwire a paper size into your code? Pin
rctaubert8-Jul-12 14:35
Memberrctaubert8-Jul-12 14:35 
GeneralRe: Why hardwire a paper size into your code? Pin
Daniel Leykauf9-Jul-12 0:11
MemberDaniel Leykauf9-Jul-12 0:11 
Had the chance to test it on different devices. If you change the line to:
VB
Dim pz As Drawing.Printing.PaperSize = Nothing
the default size will be always taken (as long as the selected paperkind does not meet an available paperkind).

The complete method in line: 383 should then look like:
VB
Private Sub _print(Optional ByVal ShowPreview As Boolean = False, Optional ByVal Owner As IWin32Window = Nothing)

    'set the page according to selected paperkind
    Dim pz As Drawing.Printing.PaperSize = Nothing
    For Each p As Drawing.Printing.PaperSize In mPrtDoc.DefaultPageSettings.PrinterSettings.PaperSizes
        If p.Kind = mPaperKind Then pz = p : Exit For
    Next

    'set the page settings
    With mPrtDoc.DefaultPageSettings
        .PaperSize = pz
        .Landscape = Landscape
        .Margins = Margins
    End With

    'show preview if required
    If ShowPreview Then
        Using dlg As New PrintPreviewDialog
            With dlg
                .ShowInTaskbar = IsNothing(Owner)
                .Text = "Preview: " & mPrtDoc.DocumentName
                .Document = mPrtDoc
                .ShowDialog(Owner)
            End With
        End Using
        Return
    End If

    mintObject = mPrtObjects.Count
    mPrtDoc.Print()
End Sub


So many thanks you for your suggestion! This will be reflected in the source code with the next update.
GeneralRe: Why hardwire a paper size into your code? Pin
rctaubert9-Jul-12 5:01
Memberrctaubert9-Jul-12 5:01 
GeneralRe: Why hardwire a paper size into your code? Pin
Daniel Leykauf26-Jul-12 7:49
MemberDaniel Leykauf26-Jul-12 7:49 
GeneralMy vote of 5 Pin
rctaubert8-Jul-12 11:38
Memberrctaubert8-Jul-12 11:38 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.