Home All Groups Group Topic Archive Search About

Determining Available Paper Sizes on Printer

Author
5 Mar 2009 6:43 PM
Rick Raisley
What would you recommend to determine the available paper sizes on a
printer? It appears that Printer.PaperSize can be used to both Set and
Determine the paper size. And it appears that setting to an unavailable size
gives an Invalid Property Value error. So I guess  I could loop through all
available sizes, and see what didn't Err.

Is there a better/easier way? Like a collection of paper sizes available?

--
Regards,

Rick Raisley
heavymetal-A-T-bellsouth-D-O-T-net

Author
5 Mar 2009 9:11 PM
Mike Williams
"Rick Raisley" <heavymetal-A-T-bellsouth-D-O-Tnet> wrote in message
news:%23SajMJcnJHA.1288@TK2MSFTNGP02.phx.gbl...

> What would you recommend to determine the available
> paper sizes on a printer? It appears that Printer.PaperSize
> can be used to both Set and Determine the paper size. And
> it appears that setting to an unavailable size gives an Invalid
> Property Value error. So I guess  I could loop through all available
> sizes, and see what didn't Err.

The problem with the looping method (apart from the time it takes) is there
are some paper sizes that do not match with the paper numbers listed in the
VB help files and on many (in fact most) printers there are also lots of
paper numbers that are not listed in the help files at all. In fact one
printer I used to own had a paper number of 32767, and you would need to
loop for a long time to get that one, considering the slow response of
Printer.PaperSize! The GetDeviceCapabilities will get the paper size
information for you though. The following example gets the paper size
information for whatever you have set as the current VB Printer, although it
is capable of course of getting such information for any printer on your
system. Paste the example into a VB Form containing a ListBox and a Command
Button.

Mike

Option Explicit
Private Declare Function DeviceCapabilities Lib _
  "winspool.drv" Alias "DeviceCapabilitiesA" _
  (ByVal lpsDeviceName As String, ByVal lpPort _
  As String, ByVal iIndex As Long, lpOutput As Any, _
  ByVal dev As Long) As Long
Private Type POINTAPI
  x As Long
  y As Long
End Type
Private Const DC_PAPERNAMES = 16
Private Const DC_PAPERS = 2
Private Const DC_PAPERSIZE = 3

Private Sub Command1_Click()
Dim lPaperCount As Long, lCounter As Long
Dim hprinter As Long, sDeviceName As String
Dim sDevicePort As String, sPaperNamesList As String
Dim sNextString As String, numPaper() As Long
Dim paperNumbers() As Integer, paperSizes() As POINTAPI
List1.Clear
lPaperCount = DeviceCapabilities(Printer.DeviceName, _
    Printer.Port, DC_PAPERNAMES, ByVal vbNullString, 0)
ReDim numPaper(1 To lPaperCount)
sPaperNamesList = String(64 * lPaperCount, 0)
' Get paper names
lPaperCount = DeviceCapabilities(Printer.DeviceName, _
    Printer.Port, DC_PAPERNAMES, ByVal sPaperNamesList, 0)
' Get matching paper numbers
ReDim paperNumbers(1 To lPaperCount)
lPaperCount = DeviceCapabilities(Printer.DeviceName, _
    Printer.Port, DC_PAPERS, paperNumbers(1), 0)
ReDim paperSizes(1 To lPaperCount)
lPaperCount = DeviceCapabilities(Printer.DeviceName, _
    Printer.Port, DC_PAPERSIZE, paperSizes(1), 0)
For lCounter = 1 To lPaperCount
  sNextString = Mid(sPaperNamesList, _
      64 * (lCounter - 1) + 1, 64)
  sNextString = Left(sNextString, _
      InStr(1, sNextString, Chr(0)) - 1)
  List1.AddItem paperNumbers(lCounter) & vbTab & vbTab _
      & Format(paperSizes(lCounter).x / 254, "0.00") & " x " _
      & Format(paperSizes(lCounter).y / 254, "0.00") _
      & " inch" & vbTab & vbTab & sNextString
Next lCounter
End Sub
Author
6 Mar 2009 2:13 PM
Rick Raisley
Thanks, Mike, that works well. and is very informative. And you're right
about looping, I looped through only the sizes given in the VB help and
online, and it worked okay, but there are a lot of other print sizes
available on many printers (including the HP LaserJet 5200 I'm using), that
you get with your routine, that wouldn't be practical with the other method.
Like 32767 for PostScript Custom Page Size. ;-)

Unfortunately, neither of these is as helpful to me as I was hoping, as it
lists all the funny sizes that we have no paper for, and which is never
loaded on a network/shared printer, so providing those options to a normal
user will just end up hanging the printer waiting for a special paper size
to be loaded. In addition, for this HP 5200, it shows, both with your
program, my process of trying to set the paper size and catching errors, and
even on the printer setup itself, that it will handle C-size sheets (17" x
22"), whereas the printer's maximum sheet size is 11x17! How weird! I mean,
the width of the printers output opening is only a bit larger than 11"

So, what I am /really/ after is what size of paper is loaded in the printer
and ready to use. I haven't found anything on that (although if you know of
something that would be great). My compromise solution, for now, is simply
to add a check box [x] User 11" x 17" paper if available. That way, I can
keep the printer set for 8 1/2" x 11" normal printing, but get the prints
using this program at 11x17 if I want them. All I do here is when printing,
save the current paper size, set the paper size to 17 (11x17), print, then
set the paper size back. It works, but it's pretty clunky method (although
easy enough for the user).

Anyhow, thanks again for your help and the very useful code.  ;-)

--
Regards,

Rick Raisley
heavymetal-A-T-bellsouth-D-O-T-net

Show quoteHide quote
"Mike Williams" <M***@WhiskyAndCoke.com> wrote in message
news:Ofg1qbdnJHA.5420@TK2MSFTNGP04.phx.gbl...
> "Rick Raisley" <heavymetal-A-T-bellsouth-D-O-Tnet> wrote in message
> news:%23SajMJcnJHA.1288@TK2MSFTNGP02.phx.gbl...
>
>> What would you recommend to determine the available
>> paper sizes on a printer? It appears that Printer.PaperSize
>> can be used to both Set and Determine the paper size. And
>> it appears that setting to an unavailable size gives an Invalid
>> Property Value error. So I guess  I could loop through all available
>> sizes, and see what didn't Err.
>
> The problem with the looping method (apart from the time it takes) is
> there are some paper sizes that do not match with the paper numbers listed
> in the VB help files and on many (in fact most) printers there are also
> lots of paper numbers that are not listed in the help files at all. In
> fact one printer I used to own had a paper number of 32767, and you would
> need to loop for a long time to get that one, considering the slow
> response of Printer.PaperSize! The GetDeviceCapabilities will get the
> paper size information for you though. The following example gets the
> paper size information for whatever you have set as the current VB
> Printer, although it is capable of course of getting such information for
> any printer on your system. Paste the example into a VB Form containing a
> ListBox and a Command Button.
>
> Mike
>
> Option Explicit
> Private Declare Function DeviceCapabilities Lib _
>  "winspool.drv" Alias "DeviceCapabilitiesA" _
>  (ByVal lpsDeviceName As String, ByVal lpPort _
>  As String, ByVal iIndex As Long, lpOutput As Any, _
>  ByVal dev As Long) As Long
> Private Type POINTAPI
>  x As Long
>  y As Long
> End Type
> Private Const DC_PAPERNAMES = 16
> Private Const DC_PAPERS = 2
> Private Const DC_PAPERSIZE = 3
>
> Private Sub Command1_Click()
> Dim lPaperCount As Long, lCounter As Long
> Dim hprinter As Long, sDeviceName As String
> Dim sDevicePort As String, sPaperNamesList As String
> Dim sNextString As String, numPaper() As Long
> Dim paperNumbers() As Integer, paperSizes() As POINTAPI
> List1.Clear
> lPaperCount = DeviceCapabilities(Printer.DeviceName, _
>    Printer.Port, DC_PAPERNAMES, ByVal vbNullString, 0)
> ReDim numPaper(1 To lPaperCount)
> sPaperNamesList = String(64 * lPaperCount, 0)
> ' Get paper names
> lPaperCount = DeviceCapabilities(Printer.DeviceName, _
>    Printer.Port, DC_PAPERNAMES, ByVal sPaperNamesList, 0)
> ' Get matching paper numbers
> ReDim paperNumbers(1 To lPaperCount)
> lPaperCount = DeviceCapabilities(Printer.DeviceName, _
>    Printer.Port, DC_PAPERS, paperNumbers(1), 0)
> ReDim paperSizes(1 To lPaperCount)
> lPaperCount = DeviceCapabilities(Printer.DeviceName, _
>    Printer.Port, DC_PAPERSIZE, paperSizes(1), 0)
> For lCounter = 1 To lPaperCount
>  sNextString = Mid(sPaperNamesList, _
>      64 * (lCounter - 1) + 1, 64)
>  sNextString = Left(sNextString, _
>      InStr(1, sNextString, Chr(0)) - 1)
>  List1.AddItem paperNumbers(lCounter) & vbTab & vbTab _
>      & Format(paperSizes(lCounter).x / 254, "0.00") & " x " _
>      & Format(paperSizes(lCounter).y / 254, "0.00") _
>      & " inch" & vbTab & vbTab & sNextString
> Next lCounter
> End Sub
>
>
Author
6 Mar 2009 3:15 PM
Rick Raisley
I notice that when looking at Printer Properties, there is a Paper Available
window, apparently showing the paper sizes actually installed in the
printer.

Any idea how to get that information from VB, rather than all the sizes the
printer can handle?

--
Regards,

Rick Raisley
heavymetal-A-T-bellsouth-D-O-T-net

Show quoteHide quote
"Rick Raisley" <heavymetal-A-T-bellsouth-D-O-Tnet> wrote in message
news:O31%23tWmnJHA.4540@TK2MSFTNGP04.phx.gbl...
> Thanks, Mike, that works well. and is very informative. And you're right
> about looping, I looped through only the sizes given in the VB help and
> online, and it worked okay, but there are a lot of other print sizes
> available on many printers (including the HP LaserJet 5200 I'm using),
> that you get with your routine, that wouldn't be practical with the other
> method. Like 32767 for PostScript Custom Page Size. ;-)
>
> Unfortunately, neither of these is as helpful to me as I was hoping, as it
> lists all the funny sizes that we have no paper for, and which is never
> loaded on a network/shared printer, so providing those options to a normal
> user will just end up hanging the printer waiting for a special paper size
> to be loaded. In addition, for this HP 5200, it shows, both with your
> program, my process of trying to set the paper size and catching errors,
> and even on the printer setup itself, that it will handle C-size sheets
> (17" x 22"), whereas the printer's maximum sheet size is 11x17! How weird!
> I mean, the width of the printers output opening is only a bit larger than
> 11"
>
> So, what I am /really/ after is what size of paper is loaded in the
> printer and ready to use. I haven't found anything on that (although if
> you know of something that would be great). My compromise solution, for
> now, is simply to add a check box [x] User 11" x 17" paper if available.
> That way, I can keep the printer set for 8 1/2" x 11" normal printing, but
> get the prints using this program at 11x17 if I want them. All I do here
> is when printing, save the current paper size, set the paper size to 17
> (11x17), print, then set the paper size back. It works, but it's pretty
> clunky method (although easy enough for the user).
>
> Anyhow, thanks again for your help and the very useful code.  ;-)
>
> --
> Regards,
>
> Rick Raisley
> heavymetal-A-T-bellsouth-D-O-T-net
>
> "Mike Williams" <M***@WhiskyAndCoke.com> wrote in message
> news:Ofg1qbdnJHA.5420@TK2MSFTNGP04.phx.gbl...
>> "Rick Raisley" <heavymetal-A-T-bellsouth-D-O-Tnet> wrote in message
>> news:%23SajMJcnJHA.1288@TK2MSFTNGP02.phx.gbl...
>>
>>> What would you recommend to determine the available
>>> paper sizes on a printer? It appears that Printer.PaperSize
>>> can be used to both Set and Determine the paper size. And
>>> it appears that setting to an unavailable size gives an Invalid
>>> Property Value error. So I guess  I could loop through all available
>>> sizes, and see what didn't Err.
>>
>> The problem with the looping method (apart from the time it takes) is
>> there are some paper sizes that do not match with the paper numbers
>> listed in the VB help files and on many (in fact most) printers there are
>> also lots of paper numbers that are not listed in the help files at all.
>> In fact one printer I used to own had a paper number of 32767, and you
>> would need to loop for a long time to get that one, considering the slow
>> response of Printer.PaperSize! The GetDeviceCapabilities will get the
>> paper size information for you though. The following example gets the
>> paper size information for whatever you have set as the current VB
>> Printer, although it is capable of course of getting such information for
>> any printer on your system. Paste the example into a VB Form containing a
>> ListBox and a Command Button.
>>
>> Mike
>>
>> Option Explicit
>> Private Declare Function DeviceCapabilities Lib _
>>  "winspool.drv" Alias "DeviceCapabilitiesA" _
>>  (ByVal lpsDeviceName As String, ByVal lpPort _
>>  As String, ByVal iIndex As Long, lpOutput As Any, _
>>  ByVal dev As Long) As Long
>> Private Type POINTAPI
>>  x As Long
>>  y As Long
>> End Type
>> Private Const DC_PAPERNAMES = 16
>> Private Const DC_PAPERS = 2
>> Private Const DC_PAPERSIZE = 3
>>
>> Private Sub Command1_Click()
>> Dim lPaperCount As Long, lCounter As Long
>> Dim hprinter As Long, sDeviceName As String
>> Dim sDevicePort As String, sPaperNamesList As String
>> Dim sNextString As String, numPaper() As Long
>> Dim paperNumbers() As Integer, paperSizes() As POINTAPI
>> List1.Clear
>> lPaperCount = DeviceCapabilities(Printer.DeviceName, _
>>    Printer.Port, DC_PAPERNAMES, ByVal vbNullString, 0)
>> ReDim numPaper(1 To lPaperCount)
>> sPaperNamesList = String(64 * lPaperCount, 0)
>> ' Get paper names
>> lPaperCount = DeviceCapabilities(Printer.DeviceName, _
>>    Printer.Port, DC_PAPERNAMES, ByVal sPaperNamesList, 0)
>> ' Get matching paper numbers
>> ReDim paperNumbers(1 To lPaperCount)
>> lPaperCount = DeviceCapabilities(Printer.DeviceName, _
>>    Printer.Port, DC_PAPERS, paperNumbers(1), 0)
>> ReDim paperSizes(1 To lPaperCount)
>> lPaperCount = DeviceCapabilities(Printer.DeviceName, _
>>    Printer.Port, DC_PAPERSIZE, paperSizes(1), 0)
>> For lCounter = 1 To lPaperCount
>>  sNextString = Mid(sPaperNamesList, _
>>      64 * (lCounter - 1) + 1, 64)
>>  sNextString = Left(sNextString, _
>>      InStr(1, sNextString, Chr(0)) - 1)
>>  List1.AddItem paperNumbers(lCounter) & vbTab & vbTab _
>>      & Format(paperSizes(lCounter).x / 254, "0.00") & " x " _
>>      & Format(paperSizes(lCounter).y / 254, "0.00") _
>>      & " inch" & vbTab & vbTab & sNextString
>> Next lCounter
>> End Sub
>>
>>
>
>
Author
7 Mar 2009 9:46 AM
Mike Williams
"Rick Raisley" <heavymetal-A-T-bellsouth-D-O-Tnet> wrote in message
news:udQAl5mnJHA.1248@TK2MSFTNGP03.phx.gbl...

> I notice that when looking at Printer Properties, there is a
> Paper Available window, apparently showing the paper
> sizes actually installed in the printer. Any idea how to get
> that information from VB, rather than all the sizes the printer can
> handle?

I'm not sure which window you are talking about? Do you mean a window on the
main manufacturer's driver dialog (the various windows that display after
you click the "Printing Preferences" button) or do you mean the initial "MS
Windows" part of the dialog (the window that first appears when you right
click the printer and select Properties)? If you mean the latter, which I
suspect you do, then you are probably talking about the information
displayed under the General tab under the "Paper Available" heading. I don't
usually deal with printers with multiple general purpose bins (such as your
HP LaserJet 5200 which appears to have two general purpose bins as standard
and a third as an optional extra) but as far as I am aware the papers listed
under "Paper Available" in that window are the paper sizes that have been
assigned as default to each of the bins, and so it will list just one page
size for each bin. Those are the paper sizes assigned to the bin by the
person who last set up the Printer Properties and it does not necessarily
mean that the paper mentioned is actually the paper that is currently
physically installed in any bin. For example if you have the permissions to
do so you should be able to click the Device Settings tab and you'll see the
various trays available and the paper size that is currently assigned to
each tray. If you click one of the trays on that window you will be able to
change the assignment to a different paper size, and thereafter that
specific size (instead of the one previously shown) will be displayed on the
General tab under the "Paper Available" heading, even though the bin in fact
does not actually contain such a paper size. So, you can only rely on that
information being true if the person who initially set it up entered the
correct information in accordance with the paper that was actually
physically installed in the trays (which of course you should have the right
to expect!) but also only if nobody else has since removed a stack of (for
example) A3 paper from a tray and substituted it with a stack of A4. For
example, on my own printer I can see A4 as the paper being available in that
window, but even if I use Printer Properties / Printing Preferences to set
the default paper size to A5 and if I place a stack of A5 paper in the tray
I can still see A4 as being available in the window we are talking about,
when of course it is not actually available at all! It is entirely possible
that people over time have done that sort of thing many times without
realising that in order to update the paper available display to its new A5
setting they must also click the Device Settings tab on the initial Printer
Properties window and change the tray asignments. I suppose that information
is better than nothing though and it might be of use to you, but I'm afraid
that at the moment I don't know how to get it. I'm sure there is a way to do
so because tray assignment appears to be a "Windows knows about this" thing
rather than a specific to driver thing. I sometimes use code to set the
paper bin and of course to set the paper size but I haven't yet looked into
determining which bin is assigned which paper size as its default. If I get
time later, or perhaps some time during the next few days depending on what
my wife has lined up for me over the weekend(!),  I'll see if I can discover
anything in the DeviceCapabilities API stuff that might help. Or perhaps
someone else here already knows how to do that? If they do then I'm sure
they'll post an answer for you.

Mike
Author
7 Mar 2009 7:30 PM
Mike Williams
"Rick Raisley" <heavymetal-A-T-bellsouth-D-O-Tnet> wrote in message
news:udQAl5mnJHA.1248@TK2MSFTNGP03.phx.gbl...

> I notice that when looking at Printer Properties, there is a Paper
> Available window, apparently showing the paper sizes actually
> installed in the printer. Any idea how to get that information . . .

Further to my previous response to this question I've now got some time to
check it out properly and I've managed to get what you have asked for using
the DeviceCapabilities function in winspool.drv in much the same way as in
the previous code I posted (which got the names and numbers of all supported
paper types for a specific printer) but using it slightly differently to get
only the names of the papers currently assigned to one of the printer's
trays by using DC_MEDIAREADY as the Index. The papers returned should agree
with the information you see against "Paper Available" on the General tab
when right clicking a printer in Control Panel and selecting Properties.
There doesn't appear to be a matching Index value to get the matching Peper
Numbers for the returned paper names (as there is when using DC_PAPERNAMES
to get the names of all papers supported by a specific printer), or at least
I can't see it at the moment, but that shouldn't matter because armed with a
list of paper names for the "Papers Available", which the following code
will get for you, you should be able to dig out the matching paper number
from the list of "paper numbers and names" generated by the previous code I
posted which lists the paper names and matching paper numbers all papers
which the printer supports. Just modify that previous code to place the
numbers and names in matching arrays (instead of merely listing them to a
ListBox as the example code currently does) and you will then be able to
pick out the appropriate paper number of the paper name generated by this
code from that array. Anyway, paste the following example into a VB Form
containing a ListBox and a Command Button. Clicking the Command button when
you run the program shpould populate the ListBox with the names of the
papers that are currently available on the printer (the papers that have
been assigned to a tray). I'll lkeave it to you to combine this code with
the code I previously posted, which generates a list of all supported papers
whether they are currently marked as available or not.

Mike

Option Explicit
Private Declare Function DeviceCapabilities Lib _
  "winspool.drv" Alias "DeviceCapabilitiesA" _
  (ByVal lpsDeviceName As String, ByVal lpPort _
  As String, ByVal iIndex As Long, lpOutput As Any, _
  ByVal dev As Long) As Long
Private Const DC_MEDIAREADY As Long = 29

Private Sub GetPapersAvailable(p1 As Printer)
Dim n As Long, p As Long, nMedia As Long
Dim sBuffer As String, MediaNames() As String
' get number of papers ready and assigned
' to a tray (the same information as you
' would get by right clicking printer in
' Control Panel and selecting Properties
' and clicking the General Tab where you
' will see the papers available (which
' you can modify under the Device Settings
' tab on the same window and altering the
' Form to Tray assignment.
nMedia = DeviceCapabilities(p1.DeviceName, _
    p1.Port, DC_MEDIAREADY, ByVal 0, 0)
If nMedia < 1 Then
List1.AddItem p1.DeviceName & " does not " _
      & "have any papers ready."
  Exit Sub ' so kick me!
End If
ReDim MediaNames(1 To nMedia)
' assign a buffer of sufficient length
' to retrieve the names of the papers
sBuffer = String$(nMedia * 64, Chr$(0))
' read the names into the buffer
n = DeviceCapabilities(p1.DeviceName, _
    p1.Port, DC_MEDIAREADY, ByVal sBuffer, 0)
' pick out the names (null terminated)
For n = 1 To nMedia
  MediaNames(n) = Mid$(sBuffer, 64 * (n - 1) + 1, 64)
  p = InStr(MediaNames(n), Chr$(0))
  If p > 0 Then
    MediaNames(n) = Left$(MediaNames(n), p - 1)
  End If
Next n
List1.Clear
List1.AddItem p1.DeviceName & " has " _
  & nMedia & " papers ready (assigned to a tray):"
For n = 1 To UBound(MediaNames)
List1.AddItem MediaNames(n)
Next n
End Sub

Private Sub Command1_Click()
GetPapersAvailable Printer
End Sub
Author
9 Mar 2009 5:36 PM
Rick Raisley
Just what I'm looking for, Mike, I'll check it out. Thanks again.  ;-)

--
Regards,

Rick Raisley
heavymetal-A-T-bellsouth-D-O-T-net

Show quoteHide quote
"Mike Williams" <M***@WhiskyAndCoke.com> wrote in message
news:%23Dwlgs1nJHA.5980@TK2MSFTNGP06.phx.gbl...
> "Rick Raisley" <heavymetal-A-T-bellsouth-D-O-Tnet> wrote in message
> news:udQAl5mnJHA.1248@TK2MSFTNGP03.phx.gbl...
>
>> I notice that when looking at Printer Properties, there is a Paper
>> Available window, apparently showing the paper sizes actually
>> installed in the printer. Any idea how to get that information . . .
>
> Further to my previous response to this question I've now got some time to
> check it out properly and I've managed to get what you have asked for
> using the DeviceCapabilities function in winspool.drv in much the same way
> as in the previous code I posted (which got the names and numbers of all
> supported paper types for a specific printer) but using it slightly
> differently to get only the names of the papers currently assigned to one
> of the printer's trays by using DC_MEDIAREADY as the Index. The papers
> returned should agree with the information you see against "Paper
> Available" on the General tab when right clicking a printer in Control
> Panel and selecting Properties. There doesn't appear to be a matching
> Index value to get the matching Peper Numbers for the returned paper names
> (as there is when using DC_PAPERNAMES to get the names of all papers
> supported by a specific printer), or at least I can't see it at the
> moment, but that shouldn't matter because armed with a list of paper names
> for the "Papers Available", which the following code will get for you, you
> should be able to dig out the matching paper number from the list of
> "paper numbers and names" generated by the previous code I posted which
> lists the paper names and matching paper numbers all papers which the
> printer supports. Just modify that previous code to place the numbers and
> names in matching arrays (instead of merely listing them to a ListBox as
> the example code currently does) and you will then be able to pick out the
> appropriate paper number of the paper name generated by this code from
> that array. Anyway, paste the following example into a VB Form containing
> a ListBox and a Command Button. Clicking the Command button when you run
> the program shpould populate the ListBox with the names of the papers that
> are currently available on the printer (the papers that have been assigned
> to a tray). I'll lkeave it to you to combine this code with the code I
> previously posted, which generates a list of all supported papers whether
> they are currently marked as available or not.
>
> Mike
>
> Option Explicit
> Private Declare Function DeviceCapabilities Lib _
>  "winspool.drv" Alias "DeviceCapabilitiesA" _
>  (ByVal lpsDeviceName As String, ByVal lpPort _
>  As String, ByVal iIndex As Long, lpOutput As Any, _
>  ByVal dev As Long) As Long
> Private Const DC_MEDIAREADY As Long = 29
>
> Private Sub GetPapersAvailable(p1 As Printer)
> Dim n As Long, p As Long, nMedia As Long
> Dim sBuffer As String, MediaNames() As String
> ' get number of papers ready and assigned
> ' to a tray (the same information as you
> ' would get by right clicking printer in
> ' Control Panel and selecting Properties
> ' and clicking the General Tab where you
> ' will see the papers available (which
> ' you can modify under the Device Settings
> ' tab on the same window and altering the
> ' Form to Tray assignment.
> nMedia = DeviceCapabilities(p1.DeviceName, _
>    p1.Port, DC_MEDIAREADY, ByVal 0, 0)
> If nMedia < 1 Then
> List1.AddItem p1.DeviceName & " does not " _
>      & "have any papers ready."
>  Exit Sub ' so kick me!
> End If
> ReDim MediaNames(1 To nMedia)
> ' assign a buffer of sufficient length
> ' to retrieve the names of the papers
> sBuffer = String$(nMedia * 64, Chr$(0))
> ' read the names into the buffer
> n = DeviceCapabilities(p1.DeviceName, _
>    p1.Port, DC_MEDIAREADY, ByVal sBuffer, 0)
> ' pick out the names (null terminated)
> For n = 1 To nMedia
>  MediaNames(n) = Mid$(sBuffer, 64 * (n - 1) + 1, 64)
>  p = InStr(MediaNames(n), Chr$(0))
>  If p > 0 Then
>    MediaNames(n) = Left$(MediaNames(n), p - 1)
>  End If
> Next n
> List1.Clear
> List1.AddItem p1.DeviceName & " has " _
>  & nMedia & " papers ready (assigned to a tray):"
> For n = 1 To UBound(MediaNames)
> List1.AddItem MediaNames(n)
> Next n
> End Sub
>
> Private Sub Command1_Click()
> GetPapersAvailable Printer
> End Sub
>
>
Author
9 Mar 2009 6:28 PM
Rick Raisley
Works perfectly, Mike. Very helpful.

Now if I can just figure out why the HP 5200, with both Letter and 11x17
paper installed, reports only Letter, both in your code AND in the printer's
property box, despite there being 11x17 paper installed and it prints fine
with it!  lol!

But anyhow, your code reported the same (although incorrect) information
that the printer dialog reports, and that's exactly what I wanted. Thanks
again!  ;-)

--
Regards,

Rick Raisley
heavymetal-A-T-bellsouth-D-O-T-net

Show quoteHide quote
"Rick Raisley" <heavymetal-A-T-bellsouth-D-O-Tnet> wrote in message
news:OB2zM2NoJHA.4872@TK2MSFTNGP04.phx.gbl...
> Just what I'm looking for, Mike, I'll check it out. Thanks again.  ;-)
>
> --
> Regards,
>
> Rick Raisley
> heavymetal-A-T-bellsouth-D-O-T-net
>
> "Mike Williams" <M***@WhiskyAndCoke.com> wrote in message
> news:%23Dwlgs1nJHA.5980@TK2MSFTNGP06.phx.gbl...
>> "Rick Raisley" <heavymetal-A-T-bellsouth-D-O-Tnet> wrote in message
>> news:udQAl5mnJHA.1248@TK2MSFTNGP03.phx.gbl...
>>
>>> I notice that when looking at Printer Properties, there is a Paper
>>> Available window, apparently showing the paper sizes actually
>>> installed in the printer. Any idea how to get that information . . .
>>
>> Further to my previous response to this question I've now got some time
>> to check it out properly and I've managed to get what you have asked for
>> using the DeviceCapabilities function in winspool.drv in much the same
>> way as in the previous code I posted (which got the names and numbers of
>> all supported paper types for a specific printer) but using it slightly
>> differently to get only the names of the papers currently assigned to one
>> of the printer's trays by using DC_MEDIAREADY as the Index. The papers
>> returned should agree with the information you see against "Paper
>> Available" on the General tab when right clicking a printer in Control
>> Panel and selecting Properties. There doesn't appear to be a matching
>> Index value to get the matching Peper Numbers for the returned paper
>> names (as there is when using DC_PAPERNAMES to get the names of all
>> papers supported by a specific printer), or at least I can't see it at
>> the moment, but that shouldn't matter because armed with a list of paper
>> names for the "Papers Available", which the following code will get for
>> you, you should be able to dig out the matching paper number from the
>> list of "paper numbers and names" generated by the previous code I posted
>> which lists the paper names and matching paper numbers all papers which
>> the printer supports. Just modify that previous code to place the numbers
>> and names in matching arrays (instead of merely listing them to a ListBox
>> as the example code currently does) and you will then be able to pick out
>> the appropriate paper number of the paper name generated by this code
>> from that array. Anyway, paste the following example into a VB Form
>> containing a ListBox and a Command Button. Clicking the Command button
>> when you run the program shpould populate the ListBox with the names of
>> the papers that are currently available on the printer (the papers that
>> have been assigned to a tray). I'll lkeave it to you to combine this code
>> with the code I previously posted, which generates a list of all
>> supported papers whether they are currently marked as available or not.
>>
>> Mike
>>
>> Option Explicit
>> Private Declare Function DeviceCapabilities Lib _
>>  "winspool.drv" Alias "DeviceCapabilitiesA" _
>>  (ByVal lpsDeviceName As String, ByVal lpPort _
>>  As String, ByVal iIndex As Long, lpOutput As Any, _
>>  ByVal dev As Long) As Long
>> Private Const DC_MEDIAREADY As Long = 29
>>
>> Private Sub GetPapersAvailable(p1 As Printer)
>> Dim n As Long, p As Long, nMedia As Long
>> Dim sBuffer As String, MediaNames() As String
>> ' get number of papers ready and assigned
>> ' to a tray (the same information as you
>> ' would get by right clicking printer in
>> ' Control Panel and selecting Properties
>> ' and clicking the General Tab where you
>> ' will see the papers available (which
>> ' you can modify under the Device Settings
>> ' tab on the same window and altering the
>> ' Form to Tray assignment.
>> nMedia = DeviceCapabilities(p1.DeviceName, _
>>    p1.Port, DC_MEDIAREADY, ByVal 0, 0)
>> If nMedia < 1 Then
>> List1.AddItem p1.DeviceName & " does not " _
>>      & "have any papers ready."
>>  Exit Sub ' so kick me!
>> End If
>> ReDim MediaNames(1 To nMedia)
>> ' assign a buffer of sufficient length
>> ' to retrieve the names of the papers
>> sBuffer = String$(nMedia * 64, Chr$(0))
>> ' read the names into the buffer
>> n = DeviceCapabilities(p1.DeviceName, _
>>    p1.Port, DC_MEDIAREADY, ByVal sBuffer, 0)
>> ' pick out the names (null terminated)
>> For n = 1 To nMedia
>>  MediaNames(n) = Mid$(sBuffer, 64 * (n - 1) + 1, 64)
>>  p = InStr(MediaNames(n), Chr$(0))
>>  If p > 0 Then
>>    MediaNames(n) = Left$(MediaNames(n), p - 1)
>>  End If
>> Next n
>> List1.Clear
>> List1.AddItem p1.DeviceName & " has " _
>>  & nMedia & " papers ready (assigned to a tray):"
>> For n = 1 To UBound(MediaNames)
>> List1.AddItem MediaNames(n)
>> Next n
>> End Sub
>>
>> Private Sub Command1_Click()
>> GetPapersAvailable Printer
>> End Sub
>>
>>
>
>
Author
9 Mar 2009 8:14 PM
Mike Williams
"Rick Raisley" <heavymetal-A-T-bellsouth-D-O-Tnet> wrote in message
news:%23f73RTOoJHA.3984@TK2MSFTNGP02.phx.gbl...

> Works perfectly, Mike. Very helpful. Now if I can just figure out why the
> HP 5200, with both Letter
> and 11x17 paper installed, reports only Letter, both in your code
> AND in the printer's property box, despite there being 11x17
> paper installed and it prints fine with it!  lol! But anyhow, your
> code reported the same (although incorrect) information that
> the printer dialog reports, and that's exactly what I wanted.
> Thanks again!  ;-)

Pleased to be of help. By the way, regarding the failure to report the 11x17
paper as being available (both my code and the printer's Properties window
in Control Panel), it is almost certainly because the 11x17 paper has not
been officially assigned to a tray, although that doesn't mean you can't use
the paper of course (as you have discovered by the fact that you can still
print to it). In fact it is possible for a printer to report that no papers
are available at all, and you will still be able to print to whatever paper
it actually contains. In fact, as I think I mentioned in one of my previous
responses in this thread, you can even deliberately set things up so that
the printer's Properties window shows A5 paper as being available for a
printer that contains only A4 paper, so that A5 paper is not actually
physically available at all, even though it is reported as being available.
In this case you would not be able to print to the paper size that is
reported as available (A5) because it is not actually available, but you
will be able to print to the paper that is not reported as available (A4).
The "papers available" details (both those that you see in the printer's
Properties window and those that are returned by the code I posted) can only
be taken as a guide. That's just the way things are. In order for the
Properties window (or the code I posted) to show the correct 'paper
available' details then the person who installed the printer, or the person
who last changed the papers it provides, needs to set up the 'paper to tray'
assignment properly.

When anyone installs a printer, whether it be multi tray or single tray, and
when they decide what paper they are normally going to place in the tray (or
trays) then they should ensure that they mark those specific paper sizes as
being available, just in case the driver installation's defaults are not
what they actually using. This is not very important in a single user
situation (a home user for example) but it is a wise thing to do when
installing a shared printer. You can make the assignments by right clicking
the printer in the Control Panel Printers applet and selecting Properties
and then clicking the Device Settings tab, where you'll see an entry for
each of the trays that the printer contains (and probably an entry for any
'optional extra' tray that the printer does not actually contain). If you
click the current entry against each tray you will see a drop down list
containing an item for each paper that the printer supports plus an
additional item called 'not available'. Select the paper size that is
actually fitted into the specific tray (or select 'not available' if the
tray is not actually fitted or if you never normally place a stack of paper
in it). Once you have done this for each of the trays then the 'Papers
Available' item on the General tab will correctly reflect all available
papers (these details are for Vista, but as I recall they are very similar
for XP). Personally I don't use network printers myself (and I think you
said that you are using such a printer) but I imagine that with such a
network printer this tray to paper assignment will need to be done at the
server end and the option to assign papers to trays may not be available at
your end (although I'm not sure on that point having never used network
printers). Anyway, once the assignment has been correctly made you should
see the correct papers, including the 11x17, in the Properties window and
the code I posted yesterday should also return it.

Mike
Author
6 Mar 2009 9:12 PM
Mike Williams
Show quote Hide quote
"Rick Raisley" <heavymetal-A-T-bellsouth-D-O-Tnet> wrote in message
news:O31%23tWmnJHA.4540@TK2MSFTNGP04.phx.gbl...

> Thanks, Mike, that works well. and is very informative. And you're
> right about looping, I looped through only the sizes given in the VB
> help and online, and it worked okay, but there are a lot of other print
> sizes available on many printers (including the HP LaserJet 5200 I'm
> using), that you get with your routine, that wouldn't be practical with
> the other method. Like 32767 for PostScript Custom Page Size. ;-)
> Unfortunately, neither of these is as helpful to me as I was hoping, as
> it lists all the funny sizes that we have no paper for, and which is
> never loaded on a network/shared printer, so providing those options
> to a normal user will just end up hanging the printer waiting for a
> special paper size to be loaded.

I'm afraid printing in Windows is still not an exact science, at least as
far as paper sizes or special printing arrangements is concerned. Some
printers are bristling with sensors that detect the size of paper (or the
presence or absence of paper) in each available tray and some are not, and
even for those that are there is still no "standard" way of communicating
such information to Windows. For example, I've just used Micro$oft Word
2007, which by its pedigree should know just about everything there is to
know about printing in Windows, to print an A4 document to my own HP printer
which was set to A5 as default and which actually contained A5 paper. The
printing was carried out without any notification from either the printer or
from Windows, with the result that the right hand half of each page was
simply missing (the A4 output flowing over the edge of the A5 paper). Some
printers behave like this and some will contain sensors that detect the
actual size of paper in each tray and notify the user accordingly when he
attempts to print something that does not actually fit on the page, with
such notification more often than not coming from message boxes displayed by
the driver rather than by Windows itself. Another thing I tried, on a
printer that does properly detect an A5 page in the main tray, was to simply
turn the A5 page around and insert it into the printer tray in landscape
orientation. This completely "foxed" the printer because the sensor measures
the paper width at the leading edge and does not in fact have any sensors to
measure its "length", thereby le4ading the printer to assume that A4 was
loaded in its standard portrait orientation.

> In addition, for this HP 5200, it shows, both with your program, my
> process of trying to set the paper size and catching errors, and even
> on the printer setup itself, that it will handle C-size sheets (17" x
> 22"),
> whereas the printer's maximum sheet size is 11x17! How weird! I mean,
> the width of the printers output opening is only a bit larger than 11"

Those kind of things vary from printer to printer. It may be that your own
LaserJet 5200 allows you to specify a 17x22 inch paper size but that it
actually prints each "page" in "multiple page poster" format, so that it in
fact prints two separate 11x17 inch sheets for each 17x22 inch page in a way
that enables you to "stick them together" after printing. Or in fact it
could be that the printer driver you are using is a "generic for the model
range" driver that can (at least in part) be used for various models in the
range.

> So, what I am /really/ after is what size of paper is loaded in
> the printer and ready to use. I haven't found anything on that
> (although if you know of something that would be great).

I'm afraid not, at least not as an unattended operation. For example many
printers which are capable of printing onto special paper sizes or onto
special media will have ways of detecting if any such media is actually
loaded in the appropriate tray (a printer that can print directly onto
printable CDs and DVDs for example) but many will not. And even on those
that do the messages "insert a disk into the CD tray" (or whatever) will be
displayed on the printer itself and Windows will in that case know nothing
about it.

The problem is that in general a lot of money has been poured into providing
standardised drivers which all obey a standard set of Windows instructions
for graphics cards (DX 10 for example) because gamers spend a lot of money
on machines and never stop spending extra money to keep up with the top end,
and there is a lot of money in "keeping them sweet", but nothing like that
amount of resources has gone into the printing side of things. Currently
lots of different manufacturers produce machines with lots of different "new
and better"! functions (in an attempt to keep the money rolling), most of
which appeal to "the average Joe Public" rather than to businesses, but
almost all of the information regarding the new or special functions is
contained in a block of memory which actually does exist in Windows (in the
extras section) but which only the printer driver actually understands. So
the printer driver (and its associated software) can do things with the
printer that Windows does not actually have any native methods for.

> My compromise solution, for now, is simply to add a check
> box [x] User 11" x 17" paper if available. That way, I can keep the
> printer set for 8 1/2" x 11" normal printing, but get
> the prints using this program at 11x17 if I want them. All I
> do here is when printing, save the current paper size, set the
> paper size to 17 (11x17), print, then set the paper size back.
> It works, but it's pretty clunky method (although easy enough
> for the user).

You don't need to save the current paper size or restore it if you are
setting the paper size using the Printer.Papersize method. That's because
all such Printer Object settings affect only the DC which the Printer Object
is currently using and they do not change the default printer settings. In
fact even if you are using the dreaded CommonDialog Control and if you are
allowing your user to select 11x17 paper in that it will still not affect
the default printer paper settings, even if CommonDialog PrinterDefault is
set to True (at least not if you are using somehting later than Win 98)
because the system allows it to change the printer itself (which is regarded
as a user setting) but not any of its properties.

Mike
Author
7 Mar 2009 1:08 AM
Ivar
Just Thought I'd mention:

I was once using an A3 printer that listed about 100 different paper sizes,
well actually about 50, but each paper size was kinda duplicated. it would
list
A4 Portrait
A4 Landscape
A3 Portrait
A3 Landscape etc etc..
The daft thing was it's own custon dialog box also had the
Portrait/Landscape option buttons! I literally had nearly a minute of fun
confusing myself :-)

Ivar