Using Common Routines

The first step in this process is to build some common routines that can be used to handle the differences between the Printer object and the Picture control.

Beginning a New Page

The WriteNewPage routine is called before I start writing anything to the preview window or the printer, as you can see in Listing 9.13. It accepts two parameters: the PrintObject and the PageNumber. The PrintObject contains an object reference to either a Printer object or the Picture control where the output will be sent. If the object is a Printer, then I need to execute the NewPage method on every page after the first. If this object is a Picture control, then all I need to do is clear the screen.

Listing 9.13: WritePage Routine in Charter

Private Sub WriteNewPage(PrintObject As Object, PageNumber As Integer)
If TypeOf PrintObject Is Printer Then
   If PageNumber > 1 Then
      PrintObject.NewPage
   End If
Else
   PrintObject.Cls
 
End If
End Sub

Ending a Print Session

After beginning a new page, I need to handle how I end the print session. This is even easier. I only need to execute the EndDoc method for the Printer object, since I don’t really want to clear the Picture control until after the user has finished viewing it. That will be handled automatically when I start the next print preview. The WriteEndDoc routine is shown in Listing 9.14.

Listing 9.14: WriteEndDoc Routine in Charter

Private Sub WriteEndDoc(PrintObject As Object)
If TypeOf PrintObject Is Printer Then
   PrintObject.EndDoc
End If
End Sub

Painting the Image

Listing 9.15 contains the simplest of the preview routines. It merely paints the specified image at the specified location. It really doesn’t need to be a separate routine; however, I included it here to show how the rest of the routines function. Basically, I supply all of the arguments necessary, followed by the PrinterObject, as parameters for this routine. Then I translate them into the single statement to paint a picture. Note that since both the Printer object and the Picture control both support the Line method, there isn’t any difference between how they are handled in this routine.

Listing 9.15: WritePicture Routine in Charter

Private Sub WritePicture(pic As Object, x1 As Single, y1 As Single, _
   PrintObject As Object)
PrintObject.PaintPicture pic, x1, y1
End Sub

Centering Text in a Rectangle

Remember how I described myself as lazy? The next routine, shown in Listing 9.16, is definitely one that looks nasty at first, but when you’ve had a chance to use it a bit, you will see how it can save a lot of work in the long run. This routine is called WriteCenter and has two siblings, WriteLeft and WriteRight, which you can read for yourself when you load this program.

Listing 9.16: WriteCenter Routine in Charter

Private Sub WriteCenter(OutputText As String, PrintObject As Object, _
   Optional x1 As Variant, Optional y1 As Variant, _
   Optional x2 As Variant, Optional y2 As Variant, _
   Optional NewBold As Variant, Optional NewItalic As Variant, _
   Optional NewUnderline As Variant, Optional NewSize As Variant, _
   Optional NewFontName As Variant)
Dim OldBold As Boolean
Dim OldItalic As Boolean
Dim OldUnderline As Boolean
Dim OldSize As Integer
Dim OldFontName As String
If Not IsMissing(NewBold) Then
   OldBold = PrintObject.Font.Bold
   PrintObject.Font.Bold = NewBold
End If
If Not IsMissing(NewItalic) Then
   OldItalic = PrintObject.Font.Italic
   PrintObject.Font.Italic = NewItalic
End If
If Not IsMissing(NewUnderline) Then
   OldUnderline = PrintObject.Font.Underline
   PrintObject.Font.Underline = NewUnderline
End If
If Not IsMissing(NewSize) Then
   OldSize = PrintObject.Font.Size
   PrintObject.Font.Size = NewSize
End If
If Not IsMissing(NewFontName) Then
   OldFontName = PrintObject.Font.Name
   PrintObject.Font.Name = NewFontName
End If
If Not (IsMissing(x1) Or IsMissing(x2)) Then
   PrintObject.CurrentX = x1 + (x2 - x1) / 2
ElseIf Not IsMissing(x1) Then
   PrintObject.CurrentX = x1
End If
If Not (IsMissing(y1) Or IsMissing(y2)) Then
   PrintObject.CurrentY = y1 + (y2 - y1) / 2
ElseIf Not IsMissing(y1) Then
   PrintObject.CurrentY = y1
End If
PrintObject.CurrentX = PrintObject.CurrentX - _
   PrintObject.TextWidth(OutputText) / 2
PrintObject.CurrentY = PrintObject.CurrentY - _
   PrintObject.TextHeight(OutputText) / 2
PrintObject.Print OutputText
If Not IsMissing(NewFontName) Then
   PrintObject.Font.Name = OldFontName
End If
If Not IsMissing(NewSize) Then
   PrintObject.Font.Size = OldSize
End If
If Not IsMissing(NewUnderline) Then
  PrintObject.Font.Underline = OldUnderline
End If
If Not IsMissing(NewItalic) Then
   PrintObject.Font.Italic = OldItalic
End If
If Not IsMissing(NewBold) Then
   PrintObject.Font.Bold = OldBold
End If
End Sub

All this routine does is to center the specified text string inside the rectangle defined the by x1, y1 and x2, y2 parameters, or centered at the location specified by x1, y1, or centered over the current cursor position. However, to make your life easier, I included most of the common font changes that you might make during the course of your program. Thus, you can easily specify any changes in the default font for a particular print item. This routine will ensure that only the specified changes are made and that the defaults are properly restored at the end of the routine.

This routine can be broken down into three parts. The first part checks to see if a parameter was supplied. If one is supplied, then the current property value is saved and the property is then set to the new value.

The second part is the actual positioning of the cursor and printing of the text. In this case, I compute the center point of where I want to print the text. If both x, y coordinates are supplied, I choose the center of the rectangle defined by them. If only one x, y coordinate is supplied, then I assume that the coordinate is the physical point where the text should be centered. If no x, y coordinates are supplied, then I assume that the current cursor position is where the text should be centered. Once I have the center point, all I do is subtract one half of the TextHeight method to determine the starting y coordinate, and subtract one half of the TextWidth method to determine the starting x coordinate. Then I can simply use the Print method to display the text.

The third part of the routine is to clean up any definitions I may have changed. Once that is done, I’m finished with this routine.

WARNING: Be careful of variable types when using Optional: The only acceptable variable type for an optional parameter is Variant. This means that it is easy to pass a String when you really need to pass an Integer. You should choose very meaningful variable names here to help the users determine the appropriate data type when Visual Basic prompts them with the list of parameters for the function.

© 1998 SYBEX Inc. All rights reserved.