loquin
03-31-2005, 11:59 AM
A common request with VB is:
"I want to print to the form, and when I need to, just dump that form to the printer. How do I do that?"
Well, every VB form has a simple, easy to use method designed to perform a quick form dump to the printer. And, it works exactly as advertised.
You just add a single statement to your codeMe.Printform
That's it. Well, THAT was easy enough. However, this approach has a shortcoming or two. If you try it, take a look at the printed output on that brand new 1200 dots per inch (dpi) laser printer. I hope you aren't expecting nice, smooth font, and crisp, clear images. Because you are NOT going to get them. What you WILL get is a fairly grainy image, as what gets printed is an exact copy of your form, at the form's current screen resolution, which is typically in the 70 to 90 dpi range. :( In addition, the PrintForm method just won't print some controls, like pictureboxes...
(There, There. Yes, I KNOW you spent a lot of money on that %$&*#! printer, but, it's REALLY not the printer's fault. It's just printing exactly what VB sent it...)
VB does support better quality printing than what you've just seen, however. It just takes a little more work, that's all. Download the attached ZIP file, and extract all the files to a project folder, and we'll get started.
Once you open the project, you'll see that there is a form, and a module. The form is just there to provide an example. The meat of the printing is located in a handful of subs in the module. So, lets talk about them.
The main Sub in the module is called PrintTheForm. Fairly descriptive. It requires one parameter - the form which you wish to print. That's it. The reason for this is pretty simple - the form is a container for other objects, so it already holds everything within it. No need to extract it out externally, in YOUR application - let the printform sub do that internally. This approach simplifies your code, and it encapsulates the code associated with printing the form.
Now, what does PrintTheForm actually do? Well, it just instanciates an object, and loops through all the objects within the form. If the objects visible property is true, it tries to print it, using a sub called PrintObject, by passing the object along to the PrintObject sub.
OK. That's simple enough. But, how does PrintObject work? Well, it is just a series of If/End If statement blocks. One block for each type of object supported. (The module, as currently written, supports the line, picturebox, imagebox, textbox, and label controls only.) We'll talk about extending the print capabilities later.
Basicly, one "If/EndIf" code block exists for each Type Of object you need to print. Each specific object type code block then calls an object-specific Print sub, again passing the object along with the call. To repeat, the object is passed along since all the pertinent details needed to print the object are contained within the object itself. For instance, let's look at a textbox. The textbox contains the text, but it also holds the font information (bold, underlined, size, italics, etc.) within, as well as the forground and background color, and the justification also. In addition, it holds the position of the textbox on the form. Since we're trying to re-create a printed image if the form, that might be important... :-\
The PrintTextBox sub accepts the textbox as its parameter. It then sets the printer font and other properties to match the textbox properties. Then it determines the position of the printed text, depending upon the justification, and prints the text contained within the textbox. Note that it uses the printer TextWidth method to calculate the printed width of the new text, using that printed width to position the text properly
The other object-specific subs act in a similar manner, in that they accept the object as a parameter, and extract all the required information needed to print the object. The only exception to this is the line, as the line width is NOT stored within the line object. The line width is actually a function of the parent form (the .DrawWidth property.) And, since this parents' property may, or may not be the same as the line as drawn on the form, I simply set it to a default value in the code, but allow the caller to change it if desired.
Now, if you need to extend the PrintForm subs to include more complex objects, it's simple enough to do. First, add another If TypeOf/End If code block in the PrintObject sub. And, you'll need to add another object-specific print sub. If you want to add a checkbox print sub, the sub would need to declare a line and a label. Then, you would draw a series of lines by instanciating a line, and calling the PrintLine Sub to print it. (4 lines to form the check box, two lines to print the .Checked value, if needed.) and finally, you would instanciate the label, copy the pertinent data from the checkbox (caption, font, alignment, etc.) to the label, and print it. Essentially, the printsubs already included with this module provide the basic building blocks to print almost any other, more complex objects.
One additional note: The printform code, as it stands, is NOT aware of containers. If you use a frame or a picturebox as a container to hold other controls, these embedded controls will not be placed correctly on the printed copy. This is because an embedded control's top and left properties are referenced to the parent control, and NOT to the 'grandparent' form. To place these controls properly, you would need to determine the parent control, get IT's top and left properties, and add them to the child's top/left properties, respectively.
Enjoy.
"I want to print to the form, and when I need to, just dump that form to the printer. How do I do that?"
Well, every VB form has a simple, easy to use method designed to perform a quick form dump to the printer. And, it works exactly as advertised.
You just add a single statement to your codeMe.Printform
That's it. Well, THAT was easy enough. However, this approach has a shortcoming or two. If you try it, take a look at the printed output on that brand new 1200 dots per inch (dpi) laser printer. I hope you aren't expecting nice, smooth font, and crisp, clear images. Because you are NOT going to get them. What you WILL get is a fairly grainy image, as what gets printed is an exact copy of your form, at the form's current screen resolution, which is typically in the 70 to 90 dpi range. :( In addition, the PrintForm method just won't print some controls, like pictureboxes...
(There, There. Yes, I KNOW you spent a lot of money on that %$&*#! printer, but, it's REALLY not the printer's fault. It's just printing exactly what VB sent it...)
VB does support better quality printing than what you've just seen, however. It just takes a little more work, that's all. Download the attached ZIP file, and extract all the files to a project folder, and we'll get started.
Once you open the project, you'll see that there is a form, and a module. The form is just there to provide an example. The meat of the printing is located in a handful of subs in the module. So, lets talk about them.
The main Sub in the module is called PrintTheForm. Fairly descriptive. It requires one parameter - the form which you wish to print. That's it. The reason for this is pretty simple - the form is a container for other objects, so it already holds everything within it. No need to extract it out externally, in YOUR application - let the printform sub do that internally. This approach simplifies your code, and it encapsulates the code associated with printing the form.
Now, what does PrintTheForm actually do? Well, it just instanciates an object, and loops through all the objects within the form. If the objects visible property is true, it tries to print it, using a sub called PrintObject, by passing the object along to the PrintObject sub.
OK. That's simple enough. But, how does PrintObject work? Well, it is just a series of If/End If statement blocks. One block for each type of object supported. (The module, as currently written, supports the line, picturebox, imagebox, textbox, and label controls only.) We'll talk about extending the print capabilities later.
Basicly, one "If/EndIf" code block exists for each Type Of object you need to print. Each specific object type code block then calls an object-specific Print sub, again passing the object along with the call. To repeat, the object is passed along since all the pertinent details needed to print the object are contained within the object itself. For instance, let's look at a textbox. The textbox contains the text, but it also holds the font information (bold, underlined, size, italics, etc.) within, as well as the forground and background color, and the justification also. In addition, it holds the position of the textbox on the form. Since we're trying to re-create a printed image if the form, that might be important... :-\
The PrintTextBox sub accepts the textbox as its parameter. It then sets the printer font and other properties to match the textbox properties. Then it determines the position of the printed text, depending upon the justification, and prints the text contained within the textbox. Note that it uses the printer TextWidth method to calculate the printed width of the new text, using that printed width to position the text properly
The other object-specific subs act in a similar manner, in that they accept the object as a parameter, and extract all the required information needed to print the object. The only exception to this is the line, as the line width is NOT stored within the line object. The line width is actually a function of the parent form (the .DrawWidth property.) And, since this parents' property may, or may not be the same as the line as drawn on the form, I simply set it to a default value in the code, but allow the caller to change it if desired.
Now, if you need to extend the PrintForm subs to include more complex objects, it's simple enough to do. First, add another If TypeOf/End If code block in the PrintObject sub. And, you'll need to add another object-specific print sub. If you want to add a checkbox print sub, the sub would need to declare a line and a label. Then, you would draw a series of lines by instanciating a line, and calling the PrintLine Sub to print it. (4 lines to form the check box, two lines to print the .Checked value, if needed.) and finally, you would instanciate the label, copy the pertinent data from the checkbox (caption, font, alignment, etc.) to the label, and print it. Essentially, the printsubs already included with this module provide the basic building blocks to print almost any other, more complex objects.
One additional note: The printform code, as it stands, is NOT aware of containers. If you use a frame or a picturebox as a container to hold other controls, these embedded controls will not be placed correctly on the printed copy. This is because an embedded control's top and left properties are referenced to the parent control, and NOT to the 'grandparent' form. To place these controls properly, you would need to determine the parent control, get IT's top and left properties, and add them to the child's top/left properties, respectively.
Enjoy.