From: Webbiz on
On Fri, 6 Nov 2009 13:00:28 -0500, "Nobody" <nobody(a)> wrote:

>"Webbiz" <nospam(a)> wrote in message
>> I'd like to select which printer to use when the print menu item is
>> selected, without changing the Default printer for the whole system.
>See "Printers collection" in MSDN. I think the example is incorrect in
>stating that "Set printer as system default.". It rather sets it application
>wide. Also, if you are using the common print dialog, the user can change
>the printer from it, so you need some code to switch Printer object to what
>the user selected. Search MSDN by title only for "Using the Print Dialog
>Box". The example below loops through Printers collection, and selects one
>by name.
>Option Explicit
>Private Sub Form_Load()
> Dim i As Long
> For i = 0 To Printers.Count - 1
> Debug.Print Printers(i).DeviceName
> If Printers(i).DeviceName Like "*HP*" Then
> Set Printer = Printers(i)
> Exit For
> End If
> Next
> If i = Printers.Count Then
> Debug.Print "No matching printer found."
> End If
>End Sub

MSDN once again giving me a migraine. :-|

Here is an example snippet from MSDN on the subject of printing text
and graphics on a form.

For example, the following procedure uses the PaintPicture method to
print a form or control�s Picture property to any output object, such
as a printer or another form:

Sub PrintAnywhere (Src As Object, Dest As Object)
Dest.PaintPicture Src.Picture, Dest.Width / 2, _
Dest.Height / 2
If Dest Is Printer Then
End If
End Sub

You then call this procedure and pass it the source and destination

PrintAnywhere MyForm, Printer

When I ran this code, I get RunTime Error 481 "Invalid Picture".

What in the world is it talking about? Invalid Picture? I was under
the assumption that the 'picture' is the graphical representation of
the form, with it's buttons and such.

From: Webbiz on
On Fri, 06 Nov 2009 15:19:58 -0300, Eduardo <mm(a)> wrote:

>In VB you can change the printer like this:
> Dim prn As Printer
> Dim iDesiredPrinterName As String
> Dim iFound As Boolean
> iDesiredPrinterName = "Printer Name"
> For Each prn In Printers
> If prn.DeviceName = iDesiredPrinterName Then
> Set Printer = prn
> iFound = True
> End If
> Next prn
> If Not iFound Then
> MsgBox "Printer '" & iDesiredPrinterName & _
> "' not found", vbInformation
> End If
>This does not affect Windows's default printer.

Using the above, I'm assuming that all the printer names will need to
be pulled from (registry?) (win.ini?) and displayed in a list so that
the user can select it. Once selected, it would then be applied to the
variable "iDesiredPrinterName".

I found this routine that appears to do that:

Private Function EnumPrintersWinNTPlus() As Long

Dim cbRequired As Long
Dim cbBuffer As Long
Dim ptr() As PRINTER_INFO_4
Dim nEntries As Long
Dim cnt As Long


'To determine the required buffer size,
'call EnumPrinters with cbBuffer set to zero.
'EnumPrinters fails, and Err.LastDLLError
'in the cbRequired parameter with the size,
'in bytes, of the buffer required to hold
'the array of structures and their data.
Call EnumPrinters(PRINTER_ENUM_LOCAL, _
vbNullString, _
0, 0, _
cbRequired, _

'The strings pointed to by each PRINTER_INFO_4
'struct's members reside in memory after the end
'of the array of structs. So we're not only
'allocating memory for the structs themselves,
'but all the strings pointed to by each struct's
'member as well.
ReDim ptr((cbRequired \ SIZEOFPRINTER_INFO_4))

'Set cbBuffer equal to the size of the buffer
cbBuffer = cbRequired

'Enumerate the printers. If the function succeeds,
'the return value is nonzero. If the function fails,
'the return value is zero.
vbNullString, _
ptr(0), cbBuffer, _
cbRequired, nEntries) Then

For cnt = 0 To nEntries - 1

With ptr(cnt)

lstPrinters.AddItem GetStrFromPtrA(.pPrinterName)

End With

Next cnt

lstPrinters.AddItem "Error enumerating printers."
End If 'EnumPrinters

EnumPrintersWinNTPlus = nEntries

End Function


So if I use your code suggestion instead of "SelectDefaultPrinter", I
should be good as golden as to setting the printer for JUST the app
calling it.

Sound right?

Thanks Eduardo.


From: Mike Williams on
"Webbiz" <nospam(a)> wrote in message

> I'd like to select which printer to use when the print
> menu item is selected, without changing the Default
> printer for the whole system . . . I'm trying to make
> this as minimal as possible.

There are lots of ways of doing that, with the most suitable way depending
on what you mean by "as minimal as possible". Do you mean you want to use a
little code as possible, or do you mean you'd like to keep the printer
selection as simple as possible for your users? In other words, do you want
to show your users a normal standard Windows printer dialog which allows
them to set all aspects of the printer they wish to use and all of its
possible settings, or would you prefer to show your users a much simpler non
standard dialog that allows them to select only the name of the printer to
be used and perhaps one or two simple options, such as orientation or
whatever? Both of those things are possible, and there are many different
ways of doing both of them. As one example of the "simple for the user"
option add a new Form to your project (name the Form formPrinter for this
example) and place one ComboBox and two Command Buttons on it and then paste
in the following code:

Private Sub Form_Activate()
Command1.Caption = "OK"
Command2.Caption = "Cancel"
Dim p As Printer
Dim element As Long
For Each p In Printers
Combo1.AddItem p.DeviceName
If p.DeviceName = Me.Tag Then
Combo1.ListIndex = element
End If
element = element + 1
Next p
If Combo1.ListIndex < 0 Then
Combo1.ListIndex = 0
End If
End Sub

Private Sub Command1_Click()
Set Printer = Printers(Combo1.ListIndex)
End Sub

Private Sub Command2_Click()
Me.Tag = ""
End Sub

You can then display the new Form as a very simple printer dialog from your
main Form (or from anywhere else) using the code:

FormPrinter.Tag = Printer.DeviceName
FormPrinter.Show vbModal

> For printing the form, I tried to use PrintForm. It did print
> the form, except it failed to include the items was were
> displayed within a picturebox that was on the form . . .

The VB PrintForm method is not worth using. The problem with parts of your
drawing failing to print is probably because your PictureBoxes are not
Autoredraw, but the PrintForm method also has various other problems
printing the contents or background of containers, especially if they are
themselves contained in other containers. I wouldn't use it if I were you.

> . . . Also, the darn thing chopped part of the right side
> of the form when printed.

That's because PrintForm prints the Form's client area at its full logical
size, which may or may not be greater than the available page width,
depending on the logical size of your Form and also on whether you are using
landscape or portrait printer orientation. For example, a typical A4 page
(in portrait orientation) has about an 8 inch printable width, which is the
equivalent of about 768 screen pixels on a typical machine running at a
setting of 96 dpi, so if the client area of your Form is wider than 768
pixels (in this specific case) then part of it will be clipped by PrintForm.

Personally I am not a great fan of printing what are effectively low
resolution screen dumps to a high resolution printer (preferring myself to
create the printed page using standard printing and drawing methods instead
of dumping a copy of a Form to it) but if you wish to keep the simplicity of
a screen dump (or a Form dump) then you would be far better off creating an
image of the Form in a memory bitmap (a hidden Autoredraw PictureBox for
example) and then using PaintPicture (or StretchBlt) to draw the image on
the printer at such a size that it will all fit into the available page size
(although this will of course cause fonts and things to appear smaller if
the logical size of your Form i much greater than the logical size of the
printer page). There are many ways of doing this, depending on whether the
Form you wish to print is fully visible on the display at the time you want
to print it (or if you are prepared to temporarily make it so), or whether
you wish to print a Form that is not fully visible on the display, and in
some cases depending on whether you wish the code to work on versions of
Windows prioer to XP. Mayayana has already posted a link to some code which
uses one of the many different possible methods of printing a Form that is
fully visible on the display, which might very well suit your needs,
otherwise if you need to print Forms that are not fully visible then post


From: Webbiz on
On Fri, 6 Nov 2009 19:39:24 -0000, "Mike Williams"
<Mike(a)> wrote:

Mayayana has already posted a link to some code which
>uses one of the many different possible methods of printing a Form that is
>fully visible on the display, which might very well suit your needs,
>otherwise if you need to print Forms that are not fully visible then post

Now I remember this. I played with that code (originally written by
Randy Birch) and could not get it to work. The screen was captured and
showed up in the picturebox, but to use this to copy my form and print
it I just ran into a wall.

Sorry for being so dense.

From: Nobody on
See this page:

Print picture to fit the page: