During this hour you will learn
Now that you've mastered Visual Basic's development environment, learned a lot of the language, and can develop working applications, you should know how Visual Basic deals with printed output. Obviously, you'll want your applications to print things sometimes. Until now, you've had no way to send information to the printer.
Be forewarned-Visual Basic's printer interface isn't as simple as most of the other VB components you've mastered. Printing data from a VB program usually isn't a trivial task. This lesson explains how to work with the several printer interfaces available to VB programmers.
One of the easiest ways to send output to your printer is to print a form. VB includes the PrintForm method that applies to any form in your project. To get output to the printer, simply write to the form by using the standard controls with the Print method you've already mastered, and then print the form.
This topic section explains the PrintForm method. Like the Print method, you apply PrintForm to your project's forms. When you issue a PrintForm method, Visual Basic begins printing the form immediately. Therefore, you must have the form ready for output before issuing PrintForm. This topic section explains how to use PrintForm to achieve the best results. You'll see that PrintForm won't suffice for much of your Visual Basic printing, but that the method works well for outputting forms to the printer.
Perhaps the biggest benefit of PrintForm, as well as VB's other printer-output capabilities, is that VB uses Windows printer objects. Thus, you never need to worry about specific printing instructions that are unique to a certain printer brand and model.![]()
Here is the syntax for the PrintForm method:
[frmFormName.]PrintForm
Notice that frmFormName is optional; if you don't specify a form name, Visual Basic applies the PrintForm method to the current form.
To print a form named frmAccPayable, you would issue the following command at the event procedure or module procedure that requires the printing:
frmAccPayable.PrintForm ' Print the Accounts Payable form
If frmAccPayable is the current form (the form with the focus whose title bar is highlighted), you can omit the form name as follows:
PrintForm ' Print the Accounts Payable form
Me refers to the current form, so you can also issue the following statement to print the current form:
Me.PrintForm ' Print the Accounts Payable form
You can return to Hour 16, "Creating VB Forms," to review the Print method. Print sends text output directly to the form. You can send output to a form with Print and then print the form with PrintForm. Remember, though, that all controls that appear on the form will also appear on the printed output.![]()
PrintForm's strength lies in its simplicity. PrintForm definitely provides the most useful and simplest printer output within Visual Basic. Unfortunately, along with PrintForm's simplicity come a few problems that you should know about.
No matter how high a resolution a user's printer can print, PrintForm prints the form at the screen's current resolution. This resolution generally goes no higher than 96 DPI (DPI means dots per inch). Printer resolutions often range as high as 600 DPI, so the form won't look as good on paper as the form looks on-screen. (96 DPI is plenty adequate for screen resolution but isn't high enough for quality printout resolution.)
You must always make sure that the form's AutoRedraw property is set to True before you print any form that contains controls and other non-text graphic elements. By default, a form's AutoRedraw property is False, meaning that the Print method prints directly atop graphical controls. If you set AutoRedraw to True, the graphic image stays in the foreground while Print does its thing behind the image and doesn't overwrite part or all of the graphic. You might use AutoRedraw's False property to create background graphics first. You then can later write text on top of it, but then set the AutoRedraw property to True immediately before printing the form, so the output appears correctly on the printer.
Be careful, because PrintForm prints those objects placed on the form at design time (and their runtime control values for controls such as labels and text boxes) only if AutoRedraw is False. Therefore, if you add graphics and pictures to a form at runtime and then want to print the form with PrintForm, be sure to set the form's AutoRedraw property to True before adding the additional items. Otherwise, the runtime additions won't appear on the printed form.
Printing is sometimes the bane of the Windows programmer. Test your application on as many different printers as possible to make sure that you're getting adequate results. You can't ensure that your printed output will look great on every printer, but you should have an idea of the results on a few common printer types if you distribute your applications to a wide range of users. Your application is dependent, of course, on users' printer drivers being properly installed and set up. Your application also depends on users selecting an appropriate printer. Your application can do only a certain amount of work toward good printing results, because the Windows printer interface takes over much of your printer interface job. Windows is only trying to help by putting this interface buffer between your application and the printer-and you certainly have to code much less than the MS-DOS programmers of old, who had to take into consideration every possible printer in existence (an impossible task because printers often came out after the code was written but before the application was distributed).![]()
You could print a text message to a blank form and then send that message to the printer like this:
Dim blnAutoRedraw As Boolean ' Holds value of AutoRedraw
'
frmBlank.Print "This is a Division Listing"
frmBlank.Print ' Blank line
frmBlank.Print "Division"; Tab(20); "Location"
frmBlank.Print "--------"; Tab(20); "--------"
frmBlank.Print "North"; Tab(20); "Widgets"
frmBlank.Print "South"; Tab(20); "Presses"
frmBlank.Print "East"; Tab(20); "Dye Tools"
frmBlank.Print "West"; Tab(20); "Grinders"
'
' Save the form's AutoRedraw Property
'
blnAutoRedraw = frmBlank.AutoRedraw
'
' Now print the form
'
frmBlank.AutoRedraw
frmBlank.PrintForm
'
' Restore the AutoRedraw Property
'
frmBlank.AutoRedraw = blnAutoRedraw
This code demonstrates saving the form's AutoRedraw property before triggering the PrintForm method. Although in this case you're probably safe setting the AutoRedraw property to True at design time (assuming that you'll never send graphics to the form elsewhere in the application), you can use this property-saving feature before you print any form.
Create a standard module property that receives a form as its argument (you can send and receive forms just as you do variable data types), saves the AutoRedraw property, and prints the form with PrintForm. This general-purpose procedure will save you from having to code the AutoRedraw-saving property each time you print with PrintForm.![]()
Any time you print, check for error conditions. The user's printer might not be turned on, might not be connected to the computer, or might not have paper. Use the On Error Goto command, as follows:
Private Sub cmdPrintForm_Click ()
Dim intBtnClicked As Integer
On Error Goto ErrHandler ' Set up error handler.
frmAccPayable.PrintForm ' Print form.
Exit Sub
ErrHandler:
intBtnClicked = MsgBox("A printer problem exists",
[ccc]vbExcalamtion, "Print Error")
End Sub
When you need to print a fill-in-the-blank form from a VB application, there's no better way to do so than to create the form and then issue the PrintForm method.![]()
You'll probably want to remove the form's title bar, control menu icon, and window buttons before printing most forms. You can temporarily hide a form and display another while your code removes these extras by setting the appropriate display property values to False.![]()
The printer that Visual Basic selects for PrintForm's output is your user's Windows default printer. What if you don't want to print to the default printer? You have access to all printers on the system. Some Windows users connect multiple printers to their systems via multiple printer ports. Also, internal faxes often act as just another printer. You can print to any printer or fax from your application by selecting the appropriate printer as Visual Basic's default printer. After you set Visual Basic's default printer, Visual Basic will route all output to that printer and ignore the system's default printer until the application ends or you designate yet another default printer.
To set a different Windows default printer from the system's Printers window, click the Windows Start button and choosing Settings and then Printers.![]()
The Printers collection is the list of all printers on the system running your application. This collection obviously changes from system to system. A user might run your application one minute, add or remove a system printer, and then run your application again, causing the application's Printers collection to vary between the two runs. This topic section explains how to access the printers in the current collection.
The Printers collection is the same list of printers that appears in the system's Print dialog box when you open theName drop-down list box.![]()
Accessing the Printers Collection
As with most lists within Visual Basic, you can reference the Printers collection from your application by using an index value. The first printer (the system default printer) has an index value of 0, the second printer has an index value of 1, and so on. If you want to use a For...Next loop to step through the printers, you can determine the number of properties now on the system by referencing Printers.Count-1. Alternatively, you can use the For Each statement to step through the printers without having to determine the number (as seen in this topic's example section).
Use the Set Printer statement to set Visual Basic's default printer to one of the printers on the system. The following statement sets Visual Basic's default printer to the second printer on the system:
Set Printer = Printers(1) ' Change the default printer
Of course, determining the printer you want to print to at runtime isn't always easy. How can you even know what kind of printer you're testing for? You can test only for specific properties. For example, if you need to print to a printer that has a certain page size, you can loop through every printer on the system, looking for one that has that page size.
Table 19.1 lists many important printer properties that you'll commonly use in determining which printer your application now needs. Most of these properties have named literal values associated with them. Therefore, rather than test for property values of 1 and 2 for a page size, you can test by using named literals such as vbPRPSLetter and vbPRPSLetterSmall. These are easier to understand later when you maintain the program (but they take longer to type).
If you look up a property in the online help reference, you'll find a list of the named literals that Visual Basic supports for that property.![]()
Table 19.1 Common Printer Object Properties
Property | Description |
ColorMode | Determines whether the printer can print in color or black and white |
Copies | Specifies the number of copies users want (set at runtime by users from the Print dialog box that your application displays, or by your code setting this property) |
CurrentX, CurrentY | Returns or sets the X and Y coordinates where the next character (or drawing) will appear |
DeviceName | Holds the name of the printer, such as Canon BubbleJet IIC |
DriverName | Holds the name of the printer (multiple printers from the same company may use the same printer driver) |
Duplex | Determines whether the printer can print to both sides of the paper or to only a single side |
Font | Returns certain font subproperty values that are set, such as Printer.Font.Bold and Printer.Font.Underline |
FontCount | Returns the number of fonts supported by the printer |
Height | Returns the height of the printed page for the selected printer (in ScaleMode measurements) |
Orientation | Determines or sets the printer's portrait or landscape orientation |
Page | Returns the current page number |
PaperBin | Returns or sets the paper bin used for printing (keep in mind, though, that not all printers support multiple bins) |
PaperSize | Returns or sets the paper size now being used |
Port | Returns the name of the printer's port |
PrintQuality | Returns or sets the printer's resolution value |
TrackDefault | If False, keeps the current printer property settings when you change default printers; if True, changes the printer property settings at runtime when you select a different default printer |
Width | Returns the width of the printed page for the selected printer (in ScaleMode measurements) |
Zoom | Returns or sets the percentage of scaling used for the printed output; for example, if you set Zoom to 75, subsequent output appears on the page at 75 percent of its regular size (not all printers support the Zoom property) |
When your application runs, the printer properties for the Printer object match those of the Windows system default printer. If you select a new default printer for VB, the properties change accordingly. At runtime, you can change many of these properties as described in Table 19.1.
You'll use many of the properties from Table 19.1 to access the specific printer-output methods introduced in the next topic section. Also, you'll learn about the Printer object's graphics-related properties in the next part of this tutorial.![]()
The next topic section explains how to use the methods related to the Printer object.
The following code demonstrates how you might step through the system's current printers:
Dim prnPrntr As Printer
For Each prnPrntr In Printers ' Steps through each
frmMyForm.Print prnPrntr.DeviceName
Next
The code simply prints each printer's name on the current form.
Notice the first line that declares a variable with the data type Printer. As you learn more about Visual Basic, you'll notice that you can declare variables of virtually any data type, including Printer and Form. The prnPrntr variable lets you walk through each printer on the system. An equivalent For statement would be
For prnPrntr = 1 to (Printers.Count - 1)
Remember that Printer and Form are Visual Basic objects. You learn more about VB objects in Hour 20, "Understanding Objects and Using the Object Browser."![]()
Rarely, if ever, would you want to print every printer's name on a form. Nevertheless, the loop shown in this example will form the basis for much of your printer processing.
The following code searches through all printers on the system, looking for a color printer to output a colorful chart:
Dim prnPrntr As Printer
For Each prnPrntr In Printers
If prnPrntr.ColorMode = vbPRCMColor Then
' Set color printer as system default.
Set Printer = prnPrntr
Exit For ' Don't look further
End If
Next ' Step through all of them if needed
The Printer object exists so that you can send data to the default printer without worrying about specific printer types and ports. You apply methods to the Printer object to route output-such as reports and graphics-to the printer. Although programming with the Printer object can be tedious, you'll develop general-purpose output procedures that can help you print more easily in subsequent programs.
Before sending output to the Printer object, set the default printer by using the previous topic section's Set Printer statement if you want the Printer object to point to a printer other than the system default printer.![]()
After you select a default printer, use the Printer object to route text and graphics to the user's printer. This topic section explains how to control the Printer object and route text to the printer. In the next part of the book, you'll learn graphics commands and methods that you can also apply to the Printer object.
In this topic section, you'll see how to build your output. This means that you send output to the Printer object, but nothing actually prints. When you've completed the output and are ready to send the completed output to the printer, you issue the NewPage or EndDoc method to start the actual printing. (Printing also begins when your application ends if you don't first issue the EndDoc method.)
Printing to the Printer Object
One of the easiest ways to route output to the Printer object is to use the Print method. The following lines send a message to the printer:
Printer.Print "This report shows sales figures for"
Printer.Print dteStart; " through "; dteFinish; "."
Printer.Print "If you need more information, call ext. 319."
You used the Print method to send output to a form in Hour 16, but as you can see here, Print is a general-purpose method that sends output to any valid object that can accept text.
You can move the print output to the top of the next page at any point by using the NewPage method:
Printer.NewPage ' Go to top of next page
When printing, you may want to scale the output to create margins on the page that subsequent printing-related methods will respect. Table 19.2 lists the properties you can set to produce a scaling effect.
Table 19.2 Scaling Properties
Property | Description |
ScaleLeft | Defines the printable area's extreme left X coordinate. For example, a ScaleLeft value of 10 moves the subsequent left margin to 10 ScaleMode measurements. |
ScaleMode | Determines the measurement value used for scaling. Generally, a ScaleMode of VbPoints (the value 2), vbCharacters (the printer's default character width), VbInches, or VbCentimeters is used for text printing. |
ScaleHeight | Changes the Printer object's vertical coordinate system. |
ScaleTop | Defines the printable area's extreme top Y coordinate. For example, a ScaleTop value of 5 moves the subsequent top margin to five ScaleMode measurements. |
ScaleWidth | Changes the Printer object's horizontal coordinate system. |
To set a top margin of five characters and a left margin of eight characters, you would issue the following methods:
Printer.ScaleMode = VbCharacters ' Set scale to chars
Printer.ScaleTop = 5
Printer.ScaleLeft = 8
Subsequent Print methods would respect these boundaries.
CurrentX and CurrentY Positions
Unless you change the coordinate system from an upper-left page coordinate of 0,0 to another X,Y system with the ScaleHeight and ScaleWidth properties, the Printer object's CurrentX and CurrentY values begin at 0,0. (The coordinates always use the measurement set by ScaleMode.) You can change these values to different X and Y coordinate values if you want to print the next item at a specific location on the page.
The CurrentX and CurrentY properties always respect the margins you've set with ScaleLeft and ScaleTop. Therefore, the coordinate pair CurrentX,CurrentY refers to the first character at the upper-left corner of the current page within any margins that you've defined.![]()
To print a message 15 lines down the page and 25 characters to the right, you would use code like this:
Printer.ScaleMode = VbCharacters
Printer.CurrentY = 14 ' Remember the starting value = 0
Printer.CurrentX = 24
Printer.Print "Warning, warning, there's danger ahead."
Visual Basic's Printer object supports several methods that let you control the printing process. You can move the printing to the top of the next page at any time by using the NewPage method:
Printer.NewPage ' Go to top of next page
At any point during the preparation for printing, issue the KillDoc method if users want to cancel the print job:
Printer.KillDoc ' Don't send the output to the printer
KillDoc completely removes your output from the Printer object. If you need to reissue the printed document later, you have to re-create the output.
KillDoc can't cancel anything that has already started printing. Also, KillDoc can't kill PrintForm jobs.![]()
Microsoft recommends creating a general-purpose printing subroutine inside a standard module that you can call from subsequent applications-as long as you include the standard module in those applications. You can use this routine to print form graphics. The that follows subroutine accepts two arguments of the Object data type. Because it receives the Object data type, you can pass the subroutine either a Form or Printer object.
Sub PrintAnywhere (Src As Object, Dest As Object)
Dest.PaintPicture Src.Picture, Dest.Width / 2, Dest.Height / 2
If TypeOf Dest Is Printer Then
Printer.EndDoc
End If
End Sub
Suppose that your application contains a form with a picture box or image that you want to display and also send to the printer. Perhaps you display a blank form for users to enter data, and then send the completed form to the printer.
This subroutine requires source and destination arguments. The source will always be the form you want to print. The destination can be Printer. You can call the procedure like this whenever you're ready to print the form:
Call PrintAnywhere (frmUserForm, Printer) ' Print form
This subroutine uses the PaintPicture method to output the form. PaintPicture draws a form on the object to which you've applied PaintPicture. The PaintPicture method requires three values: the form to draw, the destination width, and the destination height. This code simply paints a form that's one-half the size of the destination area. To ensure that the form prints at the end of this method, the If statement immediately outputs the form with the EndDoc method if the destination is the Printer object and not another form. (You could pass a second form for the destination.)
The If TypeOf statement demonstrates a kind of If you haven't seen before. The If TypeOf...Is command lets you test objects for certain data types.
The If...Is statement does more than just test for specific objects, as you'll find out in Hour 20, "Understanding Classes and Using the Object Browser."![]()
You now can route output to your printer. The easiest way to get printer output is to use PrintForm to direct an entire form to the printer; all the form's controls, text, and graphics go to the printer. Be sure to adjust the AutoRedraw property if you want the printed output to include all the form's graphics.
Before printing non-form output, you'll want to access the Printers collection, which includes an indexed list of the printers on the system. Your program can analyze the printer properties to determine which printer best meets the needs of the application. After you find an appropriate printer, you can set the default printer that the remainder of the application uses.
The Printer object accepts all output for the default printer. You can apply methods to the Printer object to scale and position printed output. The output you route to the Printer object goes into a waiting area and then goes to the printer when the application ends or when you issue the EndDoc method.
You'll learn more about objects in Hour 20. You'll learn how to build object classes to increase your programming power and decrease your effort.