School Assignment? Project Due Tomorrow? Chat LIVE With A Programming Expert!

Welcome to Dream.In.Code
Become an Expert!

Join 307,108 Programmers for FREE! Get instant access to thousands of experts, tutorials, code snippets, and more! There are 2,038 people online right now. Registration is fast and FREE... Join Now!




Printing in VB.Net

 
Reply to this topicStart new topic

> Printing in VB.Net

Rating  5
PsychoCoder
Group Icon



post 23 Feb, 2008 - 06:45 PM
Post #1


Welcome to this tutorial on Printing in VB.Net. I have been asked this question a thousand times, "Why isn't printing in VB.Net the same as it was in VB6", and the only answer I can come up with is "I don't know". It is true that printing in VB6 was much easier than what we are offered in VB.Net, but in VB.Net we have much more control over the entire print process, even setting up the document, and formatting the text.

In VB6 it was a simple call to Printer.Print and voila your document would print. But it's not that simple in VB.Net. VB.Net, beings that it is now an Object Orientated Language, requires that the developer set up the print area, determine how many lines can fit in that print area, determine print area size, margins, font and size, the works. This, as you can imagine, has been giving legacy VB programmers fits, and that is the purpose of this tutorial.

In this tutorial we will create our own printing class, and unlike many of the samples provided by Microsoft themselves, this one actually works right. Our class will inherit from the PrintDocument Class, located in the System.Drawing.Printing Namespace. Doing it this way will give us all the functionality of the PrintDocument, while allowing us, the developers, to determine items and override the default methods it contains. So now lets jump into some code (I know thats what you're waiting for).


Creating Our Class

As with any class, before we can use any of the Classes, Events and Objects available to us in the .Net Framework we need to import the Namespaces we need. For this we need but 2:These 2 Namespaces contain everything we need for this class, so you will need to add the following lines to the top of your class file:


vb

Imports System.Drawing
Imports System.Drawing.Printing



Now for the inheriting of the PrintDocument Class. To inherit from a class you need to tell your class you're inheriting from something, in our case it is the PrintDocument Class, to do this, make the following change to the declaration of your class:


vb

Public Class PCPrint : Inherits Printing.PrintDocument

End Class



So now we have a shell to work with that inherits from the PrintDocument Class, so lets add some functionality and other code to our class. In our class we will have 2 properties, one to hold the text that we are printing, and one to hold the Font we will be using when printing our document.

Adding the Font property allows us to override the default font. As with all properties, we need private modifiers for them, these are just private variables that will represent the values of our Properties. We make them private because we don't want their values to be changed directly. These will then be used for setting the value of our properties. First the variables:


vb

#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
#End Region



NOTE: You will notice all the code I offer in this tutorial is separated into sections using the #Region...#End Region blocks. This makes for faster finding of code, especially if you have a large code file.

Now for the properties, our properties are Read/Write properties so they have both a Get and Set area, allowing us to set their value, and retrieve their value:


vb

#Region " Class Properties "
''' <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

''' <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



Next we will incorporate some Constructors for our class. If you dont add Constructors, the CLR assumes an empty Constructor, this allows you to instantiate your class so you can use it. We will add both an empty Constructor, and one that accepts a parameter, the parameter will be the text we want to print.

Since we are inheriting from a seperate class, we need to call the Constructor of the base class. This is done by using MyBase.New(), this will call the Constructor of our base class, the PrintDocument Class:


vb

#Region " Class Constructors "
''' <summary>
''' Empty constructor
''' </summary>
''' <remarks></remarks>
Public Sub New()
'Call the base classes constructor
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)
'Call the base classes constructor
MyBase.New()
'Set our Text property value
_text = str
End Sub
#End Region



Now we have our Properties and our Constructors, next we will add a couple methods to our class. In our printing class we will be overriding 2 of the PrintDocument Methods, those will be the OnBeginPrint Method and the OnBeginPring Method. In the OnBeginPrint Method we will override the default font with the font we specify, and in the OnPrintPage we will be setting up the specifics of our page. We will be setting the following properties:
  • Page Size
  • Page Orientation (Landscape, Portrait)
  • Top Margin
  • Left Margin
First, the OnBeginPrint Method:


vb

#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



As you can see, here we call the base classes OnBeginPrint Method, then we check to see if a font was provided, if one wasnt we default to Times New Roman. The OnPrintpage Method is quite a bit larger and complex, this is where we will be doing the bulk of our work.

In this method we will be setting the size of the print area (the page size), we will determine if the user selected Landscape or Portrait as the print style, we will determine how many lines we are printing and how many lines will fit in our page size, and finally we will tell the printer whether we have more pages to print. Lets take a look at our overridden OnPrintPage Method:


vb

#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)

'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



You will notice that in this method we reference a function called RemoveZeros. This is the last function in our class, and it has an important role. Instead of using the legacy IIF function, or ugly nested If..Else statements, we will create a function that will check our value, and if it's a 0 (zero) we will replace it with a 1 (one). Zero's can cause bad things to happen when it comes to printing and determining page size and margins, so to alleviate that we use our RemoveZeros Function:


vb

#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



Using Our Class

And there you have it, our completed printing class. Now I know some are asking "I see this class, but how do I use it?". Well I'm glad you asked, this class is much easier to use than one would imagine. In your Form's code I would create a procedure, lets name it printDocument, then inside that procedure we would create an instance of our printer class, set its properties (PrinterFont, TextToPrint), then issue a print command, like this:


vb

#Region " PrintDocument "
Public Sub PrintDocument()
'Create an instance of our printer class
Dim printer As New PCPrint()
'Set the font we want to use
printer.PrinterFont = New Font("Verdana", 10)
'Set the TextToPrint property
printer.TextToPrint = Textbox1.Text
'Issue print command
printer.Print()
End Sub
#End Region



Then in the click event of your print button call PrintDocument, and your document will print. Thats it, thats how easy it is to use your new printer class. This class is reusable, you can incorporate it anywhere you have documents that need to be printed. If you wanted to print graphics some functionality would need to be added, those changes will be in a completely separate tutorial.

I hope you found this tutorial on Printing in VB.Net to be useful and informative, and I thank you for reading. I will be including the class used in this tutorial, but remember it is under the GPL - General Public License. With this license you can modify this code to suite your needs, but the license header must remain in tact. smile.gif

Attached File  PC_Printer.zip ( 1.77mb ) Number of downloads: 3545


Happy Coding!

This post has been edited by skyhawk133: 24 Feb, 2008 - 09:38 AM
Go to the top of the page
+Quote Post


Register to Make This Ad Go Away!

chevywes
*



post 23 Feb, 2008 - 11:07 PM
Post #2

Thanks PsychoCoder. I'll take a little break and really study what you gave me and see where I go from there.

Thanks again for all your time and help

wes
Go to the top of the page
+Quote Post

creativesoul
*



post 29 Apr, 2008 - 06:09 AM
Post #3
Hi, great code.
But something strange happens when I try to print.
It always prints to pages and the first always misses the first letter.
The second page contains only the last letter of the text I wanted to print.

Any tips on how to fix this?

This post has been edited by creativesoul: 29 Apr, 2008 - 06:10 AM
Go to the top of the page
+Quote Post

dew1969
*



post 29 Aug, 2008 - 09:13 AM
Post #4
QUOTE(creativesoul @ 29 Apr, 2008 - 07:09 AM) *

Hi, great code.
But something strange happens when I try to print.
It always prints to pages and the first always misses the first letter.
The second page contains only the last letter of the text I wanted to print.

Any tips on how to fix this?



it looks like there is an issue in the RemoveZeros

I changed the code in OnPrintPage

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

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

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

e.Graphics.DrawString(_text, _
PrinterFont, _
Brushes.Black, _
printArea, format)



hope this helps
Go to the top of the page
+Quote Post

htotten
*



post 9 Sep, 2008 - 03:11 PM
Post #5
QUOTE(dew1969 @ 29 Aug, 2008 - 10:13 AM) *

QUOTE(creativesoul @ 29 Apr, 2008 - 07:09 AM) *

Hi, great code.
But something strange happens when I try to print.
It always prints to pages and the first always misses the first letter.
The second page contains only the last letter of the text I wanted to print.

Any tips on how to fix this?



it looks like there is an issue in the RemoveZeros

I changed the code in OnPrintPage

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

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

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

e.Graphics.DrawString(_text, _
PrinterFont, _
Brushes.Black, _
printArea, format)



hope this helps



Fantastic Stuff
Go to the top of the page
+Quote Post

AndyGreen
*



post 22 Oct, 2008 - 05:15 AM
Post #6
This looks like what I've been looking for. How would you use different fonts withing the printed output. I have to display 3 of 9 barcodes and text.

Andy
Go to the top of the page
+Quote Post

diablofan
*



post 27 Dec, 2008 - 10:09 AM
Post #7
QUOTE(dew1969 @ 29 Aug, 2008 - 09:13 AM) *

QUOTE(creativesoul @ 29 Apr, 2008 - 07:09 AM) *

Hi, great code.
But something strange happens when I try to print.
It always prints to pages and the first always misses the first letter.
The second page contains only the last letter of the text I wanted to print.

Any tips on how to fix this?



it looks like there is an issue in the RemoveZeros

I changed the code in OnPrintPage

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

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

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

e.Graphics.DrawString(_text, _
PrinterFont, _
Brushes.Black, _
printArea, format)



hope this helps

I tried changing the code to the way you have it listed up there, and it doesn't work so well, it keeps printing the first page of the string. I do agree with you that RemoveZeros is flawed, but the code you printed above wouldn't work.

This code below will actually work
CODE
'Fit as many characters as we can into the print area
e.Graphics.MeasureString(PrintStr.Substring(curChar), TextFont, New SizeF(printWidth, printHeight), format, chars, lines)

'Print the Page
e.Graphics.DrawString(TextToPrint.Substring(curChar), TextFont, Brushes.Black, printArea, format)


QUOTE(AndyGreen @ 22 Oct, 2008 - 05:15 AM) *

This looks like what I've been looking for. How would you use different fonts withing the printed output. I have to display 3 of 9 barcodes and text.

Andy


For you, I would try add multiple DrawString lines like so
CODE
'Prints with multiple fonts
'First Font
e.Graphics.DrawString(TextToPrint.Substring(curChar), TextFont1, Brushes.Black, printArea, format)
'SecondFont
e.Graphics.DrawString(TextToPrint.SubString(curChar), TextFont2, Brushes.Black, printArea, format)
.... 'So on and So Forth


I'm not sure if the code above will work for you, because I haven't tried it, but here is to hoping it does biggrin.gif
Go to the top of the page
+Quote Post

palmerfh
*



post 20 Jan, 2009 - 05:49 PM
Post #8
QUOTE(diablofan @ 27 Dec, 2008 - 10:09 AM) *

QUOTE(dew1969 @ 29 Aug, 2008 - 09:13 AM) *

QUOTE(creativesoul @ 29 Apr, 2008 - 07:09 AM) *

Hi, great code.
But something strange happens when I try to print.
It always prints to pages and the first always misses the first letter.
The second page contains only the last letter of the text I wanted to print.

Any tips on how to fix this?



it looks like there is an issue in the RemoveZeros

I changed the code in OnPrintPage

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

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

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

e.Graphics.DrawString(_text, _
PrinterFont, _
Brushes.Black, _
printArea, format)



hope this helps

I tried changing the code to the way you have it listed up there, and it doesn't work so well, it keeps printing the first page of the string. I do agree with you that RemoveZeros is flawed, but the code you printed above wouldn't work.

This code below will actually work
CODE
'Fit as many characters as we can into the print area
e.Graphics.MeasureString(PrintStr.Substring(curChar), TextFont, New SizeF(printWidth, printHeight), format, chars, lines)

'Print the Page
e.Graphics.DrawString(TextToPrint.Substring(curChar), TextFont, Brushes.Black, printArea, format)


QUOTE(AndyGreen @ 22 Oct, 2008 - 05:15 AM) *

This looks like what I've been looking for. How would you use different fonts withing the printed output. I have to display 3 of 9 barcodes and text.

Andy


For you, I would try add multiple DrawString lines like so
CODE
'Prints with multiple fonts
'First Font
e.Graphics.DrawString(TextToPrint.Substring(curChar), TextFont1, Brushes.Black, printArea, format)
'SecondFont
e.Graphics.DrawString(TextToPrint.SubString(curChar), TextFont2, Brushes.Black, printArea, format)
.... 'So on and So Forth


I'm not sure if the code above will work for you, because I haven't tried it, but here is to hoping it does biggrin.gif



Hello, I was going over these posts and the code looks like something I would like to try. I download the pc_printer.zip file only to find the zip file is currupt. I see also that there is some talk about chnages to one of the funtions

Could someone post a working version of the clas module.

Thanks
Go to the top of the page
+Quote Post

diablofan
*



post 23 Jan, 2009 - 10:52 PM
Post #9
QUOTE(palmerfh @ 20 Jan, 2009 - 05:49 PM) *

snip

Hello, I was going over these posts and the code looks like something I would like to try. I download the pc_printer.zip file only to find the zip file is currupt. I see also that there is some talk about chnages to one of the funtions

Could someone post a working version of the clas module.

Thanks

The tutorial at the beginning of the article works, it just that if you add the RemoveZeros function as shown in this code here
CODE
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)

It will remove the first and last character printed

If you remove the RemoveZeros from those two lines, it will work properly. So basically the only edit needed from the original tutorial, is not putting in the RemoveZeros function. I removed it and it worked for me, so I don't see why it won't work for you. So I'd give it a shot, try it and post back results, k?
Go to the top of the page
+Quote Post

greywolv2006
*



post 12 Feb, 2009 - 06:02 AM
Post #10
Psychocoder, very grateful for your explanation. It's easy to understand.
I cannot understand what method OnPrintPage does....code works without it, so what is the reason it is there?? i'm sure there is a perfectly valid reason...but cannot see it blink.gif again, thanks very much for your help
Go to the top of the page
+Quote Post

oifwolf
*



post 2 Apr, 2009 - 01:12 PM
Post #11
thats like 3 pages of code to print text. isn't there a better way like whatever your document is Document.cut, Document.paste
Go to the top of the page
+Quote Post

KenNgHouston
*



post 21 Jun, 2009 - 01:47 PM
Post #12
Great codes. It worked very well with my inkjet, with just one minor problem.
When my printer is in sleep (energy save) mode, I have to first print a dummy page using notepad or MS Word before I may execute the codes. If I try to run the codes while the printer is sleeping, it locks up the queue / spooler.
Is there a method I can call to wake up the printer? sleeping.gif
Or how does notepad signal the printer?
Go to the top of the page
+Quote Post

Smokinghand
*



post 27 Jul, 2009 - 08:05 PM
Post #13

This works quite well. Many thanks.
Go to the top of the page
+Quote Post

PsychoCoder
Group Icon



post 27 Jul, 2009 - 08:07 PM
Post #14
Glad I could help smile.gif
Go to the top of the page
+Quote Post

lramesh
*



post 27 Sep, 2009 - 08:41 AM
Post #15
QUOTE(PsychoCoder @ 27 Jul, 2009 - 08:07 PM) *

Glad I could help smile.gif


How to handle the Printer.CurrentX & Printer.CurrentY of VB6 options. It would be great help.

Also is there any way to print image using above code(Disscussed). Also how to print multiple line like paragraph. with different fonts. Now the problem of printing multiple pages for multiple text.

This post has been edited by lramesh: 27 Sep, 2009 - 01:51 PM
Go to the top of the page
+Quote Post

snakebitcoder
*



post 2 Oct, 2009 - 10:14 AM
Post #16
I read the code you provided. It seemed right and was rather elegant (to use a word many seem fond of these days). java script:emoticon(':^:',%20'smid_4')

Leave it Microsoft to make something easy difficult. I understand that it gives total control to the programmer in controlling print, but geeze-louise, it is difficult to find understandable instructions on how to use the options (forget MSDN's forum). I find lots of stuff on using the printdocument class, but I am a bit of a nut and bolts kind of guy. I don't like having instructions that say"set it up this way and it will work." I want to know how it works and why, then what my other options are. java script:emoticon(':wub:',%20'smid_12')

Your explanation does that (to a degree), thanks. But I get an error. I am developing in vb script:emoticon(':v:',%20'smid_11')

I cut and pasted this code so I didn't fat-finger it on entry. I recompiled after every cut and paste and all went well until it got to these override statements.

Please advise and keep up the good work.

This is probably the best forum I have found on the topic.

Go to the top of the page
+Quote Post

snakebitcoder
*



post 2 Oct, 2009 - 10:25 AM
Post #17
QUOTE(snakebitcoder @ 2 Oct, 2009 - 10:14 AM) *

My first post got garbled, so I am re-adding it.

I read the code you provided. It seemed right and was rather elegant (to use a word many seem fond of these days).

Leave it Microsoft to make something easy difficult. I understand that it gives total control to the programmer in controlling print, but geeze-louise, it is difficult to find understandable instructions on how to use the options (forget MSDN's forum). I find lots of stuff on using the printdocument class, but I am a bit of a nut and bolts kind of guy. I don't like having instructions that say"set it up this way and it will work." I want to know how it works and why, then what my other options are.

Your explanation does that (to a degree), thanks. But I get an error. I am developing in vb 2008 (express edition) and I get the following errors when I compile:

Error 3 sub 'OnBeginPrint' cannot be declared 'Overrides' because it does not override a sub in a base class.

Error 4 'OnBeginPrint' is not a member of 'System.Windows.Forms.Form'.




I cut and pasted this code so I didn't fat-finger it on entry. I recompiled after every cut and paste and all went well until it got to these override statements.

Please advise and keep up the good work.

This is probably the best forum I have found on the topic.

Go to the top of the page
+Quote Post


Fast ReplyReply to this topicStart new topic
1 User(s) are reading this topic (1 Guests and 0 Anonymous Users)
0 Members:

 


Lo-Fi Version Time is now: 11/21/09 12:41PM

Live Help!

Be Social

Dream.In.Code RSS Feed Dream.In.Code LinkedIn Group Follow Us On Twitter Fan Us On Facebook

Tutorials

Programming

Web Development

Reference Sheets

Code Snippets

DIC Chatroom

Bye Bye Ads

Monthly Drawing

Thumb Drive

Top Contributors

Top 10 Kudos This Month