Question : Printing tabs in VB.NET

Using System.Drawing.Printing I am sending a textbox contents to the printer.  However,  I am losing the tabs within the textbox.  Can anyone provide me with some method which will allow the tabs?  Currently they get eaten before printing.

Thanks.

Answer : Printing tabs in VB.NET

Hello, hbash,

Yes, that's what I hoped to see.   The additions that you require are relatively few.

To demonstrate what you need to do, I created a simple form with one Button and added your iHandlePrinting class to it.  The code behind the button is essentially the same as your  PrintDocument() subroutine and is shown in the following snippet.  I have also shown the modified version of the iHandlePrinting class.  To make it easy to find the affected lines, I have marked them with a comment that starts with the characters "~~~".

You will see in my sample code for the form button that I have substituted a hard coded string for your TextBox.Text property.  For your code, just remove the lines with the hardcoded string and uncomment the original line.  

I have also changed two lines in the iHandlePrinting class that do not relate to tab stops.  I have marked these with comments beginning with the characters "~~~*".  I highly recommend that you use both "Option Explicit" and "Option Strict" in all of your coding.  The small extra effort it requires will save you from a lot of mysterious coding problems and headaches.

Oh, and just as a side note, many (perhaps most) coders use a naming convention where the first letter of the name of your iHandlePrinting class might suggest that this is an interface rather than a class.  (Admittedly, upper case "I" is used more frequently than the lower case.)

Cheers,
Randy
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim strToPrint As String = "Here is a" & vbTab & "string with some" & vbTab & _
                                   "embedded tab stops" & vbTab & "and" & vbCrLf & _
                                   vbTab & vbTab & "a new line" & vbTab & "too"

        Dim m_printer As New iHandlePrinting

        m_printer.PrinterFont = New Font("Courier New", 9, FontStyle.Bold)

        'Envy Code R VS

        m_printer.DefaultPageSettings.Margins.Left = 10
        m_printer.DefaultPageSettings.Margins.Top = 10
        m_printer.DefaultPageSettings.Margins.Bottom = 50

        'Set TextToPrint property  
        m_printer.TextToPrint = "" & vbCrLf & strToPrint                    '~~~ In your code, remove this line
        ' ''m_printer.TextToPrint = "" & vbCrLf & Me.txtSelectedRecord.Text '~~~ and uncomment this line.

        ' Set the required tab stops.  Note that each tab specification '~~~ Add lines similar to.
        ' is the offset from the previous tab.                          '~~~ this prior to invoking
        Dim sngaTabStops As Single() = {100.0F, 150.0F, 300.0F}         '~~~ the Print method.
        m_printer.TabStops = sngaTabStops                               '~~~

        'Run Print command  
        m_printer.Print()

    End Sub
End Class

Imports System.Drawing
Imports System.Drawing.Printing

Public Class iHandlePrinting : Inherits Printing.PrintDocument

#Region " Property Variables "
    ''' <summary>
    ''' Property variable for the Font the user wishes to use
    ''' </summary>
    ''' <remarks></remarks>
    Private _font As Font

    ''' <summary>
    ''' Property variable for the text to be printed
    ''' </summary>
    ''' <remarks></remarks>
    Private _text As String

    Private _tabStops As Single() = {0.0F}       '~~~ Add this array.

#End Region

#Region " Class Properties "

    Public Property TabStops() As Single()  '~~~ Add this property.
        Get                                 '~~~
            Return _tabStops                '~~~
        End Get                             '~~~
        Set(ByVal value As Single())        '~~~
            _tabStops = value               '~~~
        End Set                             '~~~
    End Property                            '~~~

    ''' <summary>
    ''' Property to hold the text that is to be printed
    ''' </summary>
    ''' <value></value>
    ''' <returns>A string</returns>
    ''' <remarks></remarks>
    Public Property TextToPrint() As String
        Get
            Return _text
        End Get
        Set(ByVal Value As String)
            _text = Value
        End Set
    End Property

    Public Function ShowPrintDialog() As Boolean    '~~~* Type should be declared!
        ShowPrintDialog(Me)
        Return True
    End Function

    Private Function ShowPrintDialog(ByRef myDocumentToPrint As PrintDocument) As Boolean    '~~~* Type should be declared!
        Dim psd As New PageSetupDialog

        With psd
            .AllowMargins = True
            .AllowOrientation = True
            .AllowPaper = True
            .AllowPrinter = True
            .ShowHelp = True
            .ShowNetwork = True

            .Document = myDocumentToPrint
        End With
        psd.ShowDialog()
        Return True
    End Function

    ''' <summary>
    ''' Property to hold the font the users wishes to use
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property PrinterFont() As Font
        ' Allows the user to override the default font
        Get
            Return _font
        End Get
        Set(ByVal Value As Font)
            _font = Value
        End Set
    End Property
#End Region

#Region " Class Constructors "
    ''' <summary>
    ''' Empty constructor
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub New()
        'Set the file stream
        MyBase.New()
        'Instantiate out Text property to an empty string
        _text = String.Empty
    End Sub

    ''' <summary>
    ''' Constructor to initialize our printing object
    ''' and the text it's supposed to be printing
    ''' </summary>
    ''' <param name="str">Text that will be printed</param>
    ''' <remarks></remarks>
    Public Sub New(ByVal str As String)
        'Set the file stream
        MyBase.New()
        'Set our Text property value
        _text = str
    End Sub
#End Region

#Region " OnBeginPrint "
    ''' <summary>
    ''' Override the default OnBeginPrint method of the PrintDocument Object
    ''' </summary>
    ''' <param name="e"></param>
    ''' <remarks></remarks>
    Protected Overrides Sub OnBeginPrint(ByVal e As Printing.PrintEventArgs)
        ' Run base code
        MyBase.OnBeginPrint(e)

        'Check to see if the user provided a font
        'if they didnt then we default to Times New Roman
        If _font Is Nothing Then
            'Create the font we need
            _font = New Font("Times New Roman", 10)
        End If
    End Sub
#End Region

#Region " OnPrintPage "
    ''' <summary>
    ''' Override the default OnPrintPage method of the PrintDocument
    ''' </summary>
    ''' <param name="e"></param>
    ''' <remarks>This provides the print logic for our document</remarks>
    Protected Overrides Sub OnPrintPage(ByVal e As Printing.PrintPageEventArgs)
        ' Run base code
        MyBase.OnPrintPage(e)

        'Declare local variables needed
        Static curChar As Integer
        Dim printHeight As Integer
        Dim printWidth As Integer
        Dim leftMargin As Integer
        Dim rightMargin As Integer
        Dim lines As Int32
        Dim chars As Int32

        'Set print area size and margins
        With MyBase.DefaultPageSettings
            printHeight = .PaperSize.Height - .Margins.Top - .Margins.Bottom
            printWidth = .PaperSize.Width - .Margins.Left - .Margins.Right
            leftMargin = .Margins.Left 'X
            rightMargin = .Margins.Top   'Y
        End With

        'Check if the user selected to print in Landscape mode
        'if they did then we need to swap height/width parameters
        If MyBase.DefaultPageSettings.Landscape Then
            Dim tmp As Integer
            tmp = printHeight
            printHeight = printWidth
            printWidth = tmp
        End If

        'Now we need to determine the total number of lines
        'we're going to be printing
        Dim numLines As Int32 = CInt(printHeight / PrinterFont.Height)

        'Create a rectangle printing are for our document
        Dim printArea As New RectangleF(leftMargin, rightMargin, printWidth, printHeight)

        'Use the StringFormat class for the text layout of our document
        Dim format As New StringFormat(StringFormatFlags.LineLimit)
        format.SetTabStops(0.0F, _tabStops)                '~~~ Add this line.

        'Fit as many characters as we can into the print area      

        e.Graphics.MeasureString(_text.Substring(RemoveZeros(curChar)), PrinterFont, New SizeF(printWidth, printHeight), format, chars, lines)

        'Print the page
        e.Graphics.DrawString(_text.Substring(RemoveZeros(curChar)), PrinterFont, Brushes.Black, printArea, format)

        'Increase current char count
        curChar += chars

        'Detemine if there is more text to print, if
        'there is the tell the printer there is more coming
        If curChar < _text.Length Then
            e.HasMorePages = True
        Else
            e.HasMorePages = False
            curChar = 0
        End If
    End Sub
#End Region

#Region " RemoveZeros "
    ''' <summary>
    ''' Function to replace any zeros in the size to a 1
    ''' Zero's will mess up the printing area
    ''' </summary>
    ''' <param name="value">Value to check</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function RemoveZeros(ByVal value As Integer) As Integer
        'Check the value passed into the function,
        'if the value is a 0 (zero) then return a 1,
        'otherwise return the value passed in
        Select Case value
            Case 0
                Return 1
            Case Else
                Return value
        End Select
    End Function
#End Region

End Class
Random Solutions  
 
programming4us programming4us