Search code examples
printingvb6picturebox

duplication avoidance when writing to picturebox and printer


So occasionally program in VB6 but I never solved this problem.

I have a Private Sub to draw lots of stuff to a picturebox like lines, text, pictures. Lots and lots of lines of code. But then i want to use same lines to draw to a printer object. But I don't know how to do it.

For example:

private sub command1_click()
    picture1.print "hello there"
    etc etc etc
end sub
private sub command2_click()
    printer.print "hello world"
    etc etc etc
    printer.print
end sub

to be

public sub pictureengine(action....)
    if action = draw then picturebox is selected for output
    if action = print then printer object is selected output 
    <object/control>.print "hello world"
    etc etc etc
    if action = print then printer.enddoc printer.print
end sub

There should be an alias to use controls/objects. Thanks in advance


Solution

  • I was faced with this exact issue. I decided to abstract away the details of the PictureBox, Printer, or any other surface by implementing Interfaces. You will end up with 3 classes:

    • ISurface
    • CPrinterSurface
    • CPictureBoxSurface

    The ISurface Class defines the interface and contains no code:

    Option Explicit
    
    Public Sub Create(ByRef SurfaceObject As Object)
    End Sub
    
    Public Sub AddLine(ByVal StartX As Double, _
                       ByVal StartY As Double, _
                       ByVal EndX As Double, _
                       ByVal EndY As Double, _
                       Optional ByVal PenColor As Long = vbWhite, _
                       Optional ByVal PenSize As Integer = 1, _
                       Optional ByVal PenStyle As DrawStyleConstants = vbSolid)
    End Sub
    
    Public Sub AddCircle(ByVal StartX As Double, _
                         ByVal StartY As Double, _
                         ByVal Radius As Double, _
                         Optional ByVal PenColor As Long = vbWhite, _
                         Optional ByVal PenSize As Integer = 1, _
                         Optional ByVal PenStyle As DrawStyleConstants = vbSolid)
    End Sub
    

    The CPrinterSurface Class implements the interface. This is where you add code.

    Option Explicit
    
    Implements ISurface
    
    Private oPrinter As Printer
    
    Private Sub ISurface_Create(SurfaceObject As Object)
       Set oPrinter = SurfaceObject
    End Sub
    
    Private Sub ISurface_AddLine(ByVal StartX As Double, _
                                 ByVal StartY As Double, _
                                 ByVal EndX As Double, _
                                 ByVal EndY As Double, _
                                 Optional ByVal PenColor As Long = 16777215, _
                                 Optional ByVal PenSize As Integer = 1, _
                                 Optional ByVal PenStyle As DrawStyleConstants = 0&)
       oPrinter.DrawWidth = PenSize
       oPrinter.DrawStyle = PenStyle
       oPrinter.ForeColor = PenColor       
       oPrinter.Line (StartX, StartY)-(EndX, EndY), PenColor
    End Sub
    
    Private Sub ISurface_AddCircle(ByVal StartX As Double, _
                                   ByVal StartY As Double, _
                                   ByVal Radius As Double, _
                                   Optional ByVal PenColor As Long = 16777215, _
                                   Optional ByVal PenSize As Integer = 1, _
                                   Optional ByVal PenStyle As DrawStyleConstants = 0&)
       oPrinter.DrawWidth = PenSize
       oPrinter.DrawStyle = PenStyle
       oPrinter.ForeColor = PenColor
       oPrinter.Circle (StartX, StartY), Radius, PenColor
    End Sub
    

    The CPictureBoxSurface Class also implements the interface.

    Option Explicit
    
    Implements ISurface
    
    Private oPictureBox As PictureBox
    
    Private Sub ISurface_Create(SurfaceObject As Object)
       Set oPictureBox = SurfaceObject
    End Sub
    
    Private Sub ISurface_AddLine(ByVal StartX As Double, _
                                 ByVal StartY As Double, _
                                 ByVal EndX As Double, _
                                 ByVal EndY As Double, _
                                 Optional ByVal PenColor As Long = 16777215, _
                                 Optional ByVal PenSize As Integer = 1, _
                                 Optional ByVal PenStyle As DrawStyleConstants = 0&)
       oPictureBox.DrawWidth = PenSize
       oPictureBox.DrawStyle = PenStyle
       oPictureBox.ForeColor = PenColor       
       oPictureBox.Line (StartX, StartY)-(EndX, EndY), PenColor
    End Sub
    
    Private Sub ISurface_AddCircle(ByVal StartX As Double, _
                                   ByVal StartY As Double, _
                                   ByVal Radius As Double, _
                                   Optional ByVal PenColor As Long = 16777215, _
                                   Optional ByVal PenSize As Integer = 1, _
                                   Optional ByVal PenStyle As DrawStyleConstants = 0&)
       oPictureBox.DrawWidth = PenSize
       oPictureBox.DrawStyle = PenStyle
       oPictureBox.ForeColor = PenColor
       oPictureBox.Circle (StartX, StartY), Radius, PenColor
    End Sub
    

    The Main App. Create an EXE project containing the logic to generically produce your drawing. Swap out the surface, and one codebase can draw to any implemented surface. Your project tree will consist of the main form with a PictureBox and a Button, and the 3 classes described above. Here is the code for the main form:

    Option Explicit
    
    Private MySurface As ISurface
    
    Private Sub cmdCreate_Click()
       Set MySurface = New CPictureBoxSurface
       MySurface.Create Picture1
       MySurface.AddCircle 1000, 1000, 500, vbRed
       MySurface.AddCircle 1500, 1500, 500, vbBlue
    End Sub
    

    The code presented above eliminates duplication when you have multiple surfaces. It has been stripped down for clarity and to highlight the basic architecture. Hopefully you will be able to expound upon these concepts for your application.