Upgrading the Printer Object

In Visual Basic 6.0, the Printer object enables applications to communicate with a system printer. The Printer object contains functions for printing text, lines, and images. However, the printing model in the .NET Framework is quite different from that in Visual Basic 6.0. The Printer object has become obsolete. Fortunately, the functionality of the Printer object can be achieved with the classes that are provided in the System.Drawing.Printing namespace, particularly the PrintDocument class.

There are two main options to upgrade the Visual Basic 6.0 printing functionality. The first option is to replace the Printer object members with equivalent functionality provided by the PrintDocument class. Typically, this requires reimplementation of the functionality; this will be demonstrated in the next code example. The second option is to create your own Printer class in Visual Basic .NET based on the .NET PrintDocument class. This approach will allow you to mask the .NET PrintDocument class functionality with the names provided in the Visual Basic 6.0 Printer object. This second option will also be demonstrated later in this section.

Applying the first approach will require reimplementation of the printing code. The following Visual Basic 6.0 code example prints four lines of text with different font settings:

Private Sub Form_Load() With Printer

Printer.Print "Normal Line" .FontBold = True Printer.Print "Bold Line" .FontItalic = True

Printer.Print "Bold and Italic Line" .FontBold = False .FontItalic = False Printer.Print "Second Normal Line" .EndDoc End With End Sub

This code can be reimplemented in Visual Basic .NET using methods of the PrintDocument class, as shown here.

Dim WithEvents prn As New Printing.PrintDocument

Private Sub Form1_Load(ByVal eventSender As System.Object, _ ByVal eventArgs As System.EventArgs) Handles MyBase.Load prn.Print() End Sub

Private Sub prn_PrintPage(ByVal sender As Object, _

ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles prn.PrintPage Dim currFont As Font

Dim yPos As Integer yPos = 1

With e.Graphics currFont = New Font("Arial", 10, FontStyle.Regular) .DrawString("Normal Line", currFont, Brushes.Black, 1, yPos) yPos = yPos + currFont.GetHeight currFont = New Font("Arial", 10, FontStyle.Bold) .DrawString("Bold Line", currFont, Brushes.Black, 1, yPos) yPos = yPos + currFont.GetHeight currFont = New Font("Arial", 10, FontStyle.Bold Or FontStyle.Italic) .DrawString("Bold and Italic Line", currFont, Brushes.Black, 1, yPos) yPos = yPos + currFont.GetHeight currFont = New Font("Arial", 10, FontStyle.Regular) .DrawString("Second Normal Line", currFont, Brushes.Black, 1, yPos) End With End Sub

Notice how the structure of the code has changed and how the quantity of drawing methods has increased. The .NET Framework provides more control and power over the drawing operations, but from the upgrade point of view, it has a learning curve, and the manual reimplementation of all the printing functionality can consume extensive resources.

For more information about the equivalent functionality for the Printer object members, see Tables 7.3 and 7.4 at the end of this section. For further guidance on printing from Visual Basic .NET with the PrintDocument component, see "Printing with the PrintDocument Component" in on MSDN.

The second upgrade approach involves the creation of your own Printer class. This allows you to consolidate several drawing methods and collections of graphical objects (such as Circle or Line) and to store the coordinates that will be used to print these objects when the Print method or the EndDoc method is called. When the Print method of the PrintDocument class is called, the PrintPage event is raised. This event can be used to signal the application to draw all the objects and text stored in the collections of your PrinterClass. The following Visual Basic .NET code provides a small demonstration of how this Printer class can be developed.

Imports Microsoft.VisualBasic.Compatibility ' Imports Microsoft.VisualBasic. Public Class PrinterClass

Public Enum FillStyleConstants As Short vbFSSolid = 0 vbFSTransparent = 1 End Enum

' Scale mode Constants Public Enum ScaleModeConstants As Short vbTwips = 1

vbPixels = 3 End Enum

Private Structure LineInfo

Dim pen As System.Drawing.Pen Dim pl, p2 As Drawing.Point End Structure

Private Structure RectangleInfo Dim pen As System.Drawing.Pen Dim rec As Drawing.Rectangle Dim FillStyle As FillStyleConstants Dim FillColor As System.Drawing.Color End Structure

Private Structure PageInfo

Public Lines() As LineInfo Public Circ1es() As RectangleInfo End Structure

Private Pages() As PageInfo Private PageIndex = 0

Private WithEvents InnerPrinter As New System.Drawing.Printing.PrintDocument Private objPen As New System.Drawing.Pen(System.Drawing.Brushes.Black) Private intCurrentX As Double = 20 Private intCurrentY As Double = 20

Public ScaleMode As ScaleModeConstants = ScaleModeConstants.vbTwips Public FillColor As Drawing.Color

Public FillStyle As FillStyleConstants = FillStyleConstants.vbFSTransparent

Public Sub New() ReDim Pages(0) Pages(0) = New PageInfo End Sub

' Terminates a print operation sent to the Printer object, ' releasing the document to the print device or spooler. Public Sub EndDoc() Dim j As Integer For j = 0 To Pages.Length - l PageIndex = j InnerPrinter.Print()

Next End Sub

Public Sub Circ1e(ByVa1 P As Drawing.Point, ByVal radius As Double, _ Optional ByVal [Step] As Boolean = False) Circ1e(P, radius, objPen.Color, [Step]) End Sub

Public Sub Circ1e(ByVa1 P As Drawing.Point, ByVal radius As Double, _ ByVal Color As Drawing.Color, _ Optional ByVal [Step] As Boolean = False)

Dim diameter As Double

P.X = P.X + CurrentX P.Y = P.Y + CurrentY End If diameter = radius * 2

' Moves the CurrentX and CurrentY properties CurrentX = P.X + radius CurrentY = P.Y + radius

P.X = ConvertToPixelsX(P.X) P.Y = ConvertToPixelsY(P.Y) diameter = ConvertToPixelsX(diameter)

If IsNothing(Pages(PageIndex).Circles) Then ReDim Preserve Pages(PageIndex).Circles(0)

Else

ReDim Preserve

Pages(PageIndex).Circles(Pages(PageIndex).Circles.Length) End If

Pages(PageIndex).Circles(Pages(PageIndex).Circles.Length

New Drawing.Rectangle(P.X, P.Y, diameter, diameter) Pages(PageIndex).Circles(Pages(PageIndex).Circles.Length Pages(PageIndex).Circles(Pages(PageIndex).Circles.Length

FillColor

Pages(PageIndex).Circles(Pages(PageIndex).Circles.Length FillStyle

End Sub

Private Sub Printer_PrintPage(ByVal sender As Object, _

ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles InnerPrinter.PrintPage Dim i As Integer ' Draw all circles

If IsNothing(Pages(PageIndex).Circles) = False Then For i = 0 To Pages(PageIndex).Circles.Length - 1 Dim x, y As Integer e.Graphics.DrawEllipse(Pages(PageIndex).Circles(i).pen,

Pages(PageIndex).Circles(i).rec) If Pages(PageIndex).Circles(i).FillStyle = _ FillStyleConstants.vbFSSolid Then e.Graphics.FillEllipse( _

New Drawing.SolidBrush( _ Pages(PageIndex).Circles(i).FillColor), _ Pages(PageIndex).Circles(i).rec)

End If

Next End If End Sub

Public Property CurrentX() As Double Get

Return ConvertToPixelsX(intCurrentX) End Get

Set(ByVal Value As Double)

intCurrentX = ConvertToPixelsX(Value) End Set

End Property

Public Property CurrentY() As Double Get

Return ConvertToPixelsY(intCurrentY) End Get

Set(ByVal Value As Double)

intCurrentY = ConvertToPixelsY(Value) End Set End Property

Public Function ConvertToPixelsX(ByVal num As Double) As Double Return IIf(ScaleMode = ScaleModeConstants.vbTwips, _ VB6.TwipsToPixelsX(num), num)

End Function

Public Function ConvertToPixelsY(ByVal num As Return IIf(ScaleMode = ScaleModeConstants VB6.TwipsToPixelsY(num), num)

End Function End Class

Tables 7.3 and 7.4 list Visual Basic 6.0 Printer object properties and methods and their Visual Basic .NET equivalents. Where there are no direct equivalents, links are provided to additional information.

The following example shows you how to convert Visual Basic 6.0 code that uses a printer object to Visual Basic .NET code that uses your own printer class as mentioned earlier.

Printer.FillColor = vbBlue Printer.FillStyle = vbSolid Printer.Circle (3000, 3000), 1500, vbRed Printer.EndDoc

The preceding Visual Basic 6.0 code will print a circle filled with blue color and it will have a red border. To convert this code to Visual Basic .NET, you can use the printer class mentioned earlier and perform the following steps.

First, you have to add this printer class to the .NET project. After this, you have to add a reference to the Micosoft.VisualBasic.Compatibility assembly.

The next step is to create a Visual Basic .NET module and add the following code.

Module Module1

Public Printer As PrinterClass = New PrinterClass End Module

Finally, you need to perform some small changes to the original Visual Basic 6.0 code to make it consistent with the new definition of your own printer class. Here is the resulting Visual Basic .NET code.

Printer.FillColor = Color.Blue

Printer.FillStyle = PrinterClass.FillStyleConstants.vbFSSolid Printer.Circle(New Point(3000, 3000), 1500, Color.Red) Printer.EndDoc()

Double) As Double .vbTwips, _

Table 7.3: Visual Basic .NET Equivalents for Printer Object Properties Visual Basic 6.0 Visual Basic .NET Equivalent

ColorMode

PrintDocument.PrinterSettings.DefaultPageSettings.Color

Copies

PrintDocument.PrinterSettings.Copies

CurrentX

No equivalent. Replaced by location and dimension arguments of various methods of the Graphics class.This property could be simulated in your printer class with a double variable.

CurrentY

No equivalent. Replaced by location and dimension arguments of various methods of the Graphics class.This property could be simulated in your printer class with a double variable.

DeviceName

PrintDocument.PrinterSettings.PrinterName

DrawMode

No equivalent. For details, see "Graphics Changes in Visual Basic .NET" on MSDN.

DrawStyle

System.Drawing.Drawing2D.DashStyle

DrawWidth

System.Drawing.Pen.Width

DriverName

No equivalent. No longer needed; printer drivers are managed by Windows.

Duplex

System.Drawing.Printing.Duplex

FillColor

No equivalent. For details, see "Graphics Changes in Visual Basic .NET" on MSDN.This property could be simulated in your printer class with a System.Drawing.Color variable.

FillStyle

This functionality can be obtained using a Drawing.SolidBrush to fill the Draws objects.

Font

This property could be simulated in your printer class with a System.Drawing.Font class.

FontBold

To get the value, use: System.Drawing.Font.Bold.To set the value, use: VB6.FontChangeBold.

FontCount

System.Drawing.FontFamily.GetFamilies().Length

FontItalic

To get the value, use: System.Drawing.Font.Italic.To set the value, use: VB6.FontChangeItalic.

FontName

To get the value, use: System.Drawing.Font.Name.To set the value, use: VB6.FontChangeName.

Fonts

System.Drawing.FontFamily.GetFamilies

FontSize

To get the value, use: System.Drawing.Font.Size.To set the value, use: VB6.FontChangeSize.

FontStrikethru

To get the value, use: System.Drawing.Font.Strikeout.To set the value, use: VB6.FontChangeStrikeout.

continued continued

Visual Basic 6.0 Visual Basic .NET Equivalent

FontTransparent

No equivalent. For details, see "Font Changes in Visual Basic .NET" in Visual Basic Concepts on MSDN.

FontUnderline

To get the value, use: System.Drawing.Font.Underline.To set the value, use: VB6.FontChangeUnderline.

ForeColor

System.Drawing.Pen.Color

hDC

PrintDocument.PrinterSettings.GetHdevmode.ToInt32

Height

PrintDocument.DefaultPageSettings.PaperSize.Height

Orientation

PrintDocument.DefaultPageSettings.Landscape

Page

No direct equivalent. The current page number is not tracked; however, you can easily do this by setting a variable in the BeginPrint event and incrementing it in the PrintPage event.

PaperBin

PrintDocument.PrinterSettings.PaperSources

PaperSize

PrintDocument.DefaultPageSettings.PaperSize

Port

No longer necessary. The PrintPreviewDialog control automatically sets port information.

PrintQuality

PrintDocument.DefaultPageSettings.PrinterResolution

RightToLeft

No longer necessary. The direction of printing is controlled by the localization settings in Windows.

ScaleHeight

No equivalent. For details, see "Coordinate System Changes in Visual Basic .NET" in Visual Basic Concepts on MSDN.

ScaleLeft

No equivalent. For details, see "Coordinate System Changes in Visual Basic .NET" on MSDN.

ScaleMode

No equivalent. For details, see "Coordinate System Changes in Visual Basic .NET" on MSDN.

ScaleTop

No equivalent. For details, see "Coordinate System Changes in Visual Basic .NET" on MSDN.

ScaleWidth

No equivalent. For details, see "Coordinate System Changes in Visual Basic .NET" on MSDN.

TrackDefault

No direct equivalent. The IsDefaultPrinter property of the PrinterSettings class can be used to determine whether a printer is the default, but printing is no longer halted if the default printer changes.

TwipsPerPixelX

No longer necessary. Measurements in Visual Basic .NET are always in pixels.

TwipsPerPixelY

No longer necessary. Measurements in Visual Basic .NET are always in pixels.

Width

PrintDocument.DefaultPageSettings.PaperSize.Height

Zoom

No longer necessary. If the printer has zoom capabilities, settings are automatically exposed in the Print dialog box.

Table 7.4: Visual Basic .NET equivalents for Printer object methods Visual Basic 6.0 Visual Basic .NET Equivalent

Circle

PrintPageEvents.Graphics.DrawEllipse

EndDoc

PrintDocument.Print

KillDoc

PrintEventArgs.Cancel

Line

PrintPageEvents.Graphics.DrawLine

NewPage

This method needs to be simulated with an array of pages and call the method Print of the class PrintDocument for each page.

PaintPicture

PrintPageEvents.Graphics.DrawImage

Print

PrintPageEvents.Graphics.DrawString

PSet

PrintPageEvents.Graphics.DrawLine

Scale

No equivalent. For details, see "Coordinate System Changes in Visual Basic .NET" in Visual Basic Concepts on MSDN.

ScaleX

No equivalent. For details, see "Coordinate System Changes in Visual Basic .NET" on MSDN.

ScaleY

No equivalent. For details, see "Coordinate System Changes in Visual Basic .NET" on MSDN.

TextHeight

System.Drawing.Graphics.MeasureString

TextWidth

System.Drawing.Graphics.MeasureString

Upgrading the Printers Collection

Visual Basic 6.0 provides the Printers collection, which is used to return information about available printers on a system. For example, it is possible to determine the printer layout for a particular printer. Visual Basic .NET does not support the Printers collection. The printing model has changed, and as a result, references to the Printers collection require manual adjustment when upgrading to Visual Basic .NET.

Consider the following Visual Basic 6.0 example, which uses the Printers collection to find the first available printer with its page orientation set to Portrait. If such a printer is found in the collection, a message box showing the printer device name is displayed. The code for the example follows.

Dim prn As Printer For Each prn In Printers

If prn.Orientation = vbPRORPortrait Then MsgBox prn.DeviceName ' Stop looking for a printer. Exit For End If Next

Because the Printers collection is not supported in Visual Basic .NET, this code cannot be automatically upgraded with the upgrade wizard. Applying the upgrade wizard results in the code being marked with upgrade issues, such as the one demonstrated here.

' UPGRADE_ISSUE: Printers collection was not upgraded. For Each prn In Printers

The only way to achieve a similar effect in Visual Basic .NET is to implement your own Printers collection, using various classes the Microsoft .NET Framework provides. For example, you can create a new Visual Basic .NET module and class like the following.

Module PrintersModule

Public Printers As New PrintersCollection End Module

Public Class PrintersCollection : Implements IEnumerable

Private printer As System.Drawing.Printing.PrinterSettings

Public ReadOnly Property Count() As Integer Get

Return System.Drawing.Printing.PrinterSettings.InstalledPrinters.Count End Get End Property

Public ReadOnly Property Item(ByVal Index As Integer) _

As System.Drawing.Printing.PrinterSettings

Get printer = New System.Drawing.Printing.PrinterSettings printer.PrinterName = _

System.Drawing.Printing.PrinterSettings.InstalledPrinters.Item(Index) Return printer End Get End Property

Overridable Function GetEnumerator() As IEnumerator _

Implements IEnumerable.GetEnumerator

Dim Count As Integer = _

System.Drawing.Printing.PrinterSettings.InstalledPrinters.Count Dim printersArray(Count) As System.Drawing.Printing.PrinterSettings Dim i As Integer For i = 0 To Count - 1

printersArray(i) = New System.Drawing.Printing.PrinterSettings printersArray(i).PrinterName = _

System.Drawing.Printing.PrinterSettings.InstalledPrinters.Item(i)

Next

Return printersArray.GetEnumerator() End Function End Class

After the preceding module and class are created and added to the upgrade solution, the original code can be upgraded with only a few minor tweaks. These are shown here (changes are highlighted in bold).

Dim prn As System.Drawing.Printing.PrinterSettings

For Each prn In Printers

If prn.DefaultPageSettings.Landscape = False Then MsgBox(prn.PrinterName)

Exit For End If Next

For more information about replacing the Printers collection functionality in Visual Basic .NET, see "Printers Collection Changes in Visual Basic .NET" in Visual Basic Concepts on MSDN.

Was this article helpful?

+1 0

Post a comment