Subject Re: printer paper source
From Mervyn Bick <invalid@invalid.invalid>
Date Mon, 10 Aug 2020 11:30:19 +0200
Newsgroups dbase.getting-started
Attachment(s) paperbin.prg

On 2020-08-09 16:27, Ken Mayer wrote:

>> The one thing I noticed, both with this and with Rick's is that the
>> last item doesn't show any text, just the number. So with my HP 1020,
>> it shows:
>> HP LaserJet 1020
>>           7 - Auto Select
>>           4 -
>> Not quite as useful ...
> Using the same printer, in the Command Window:
> inspect( _app.printer )
> selecting paperSource and clicking the tool button, the dialog shows
> both "Auto Select" and "Manual Feed", so the information has to be there
> ....
We're back to the definition of test data.  The only data with which the
program will actually work. :-)  I only have the one printer and it only
has one paper bin so the program returned the correct information.  I
hadn't thought to try it on PDF995 which has two bin options.

When all else fails, RTFM! :-)

I had simply copied Rick Miller's code and made a few changes.  I've now
done what I should have done in the first place.  I've checked the
Windows API documentation for DeviceCapabilitiesA().  The paper size
description can be 64 characters.  The paper bin names are a maximum of
24 characters.  Duh!  A simple fix and the program now returns all the
bin options correctly.

I've also moved one line of code so that the device name lists for both
the default printer and a named printer.  It's perhaps a good idea to do
the same for PaperSize.prg


   This a direct copy of PapeSize.prg posted by Rick Miller with the necessary
   changes so as to be able to identify the available paper sources.
   2020-08-09   Mervyn Bick
   This program will return the binName and PapeBin information
   for the default printer. The number returned for each option
   could then be used for a report. This is really not a production
   program, but meant to be used by a developer to help as needed.
   Output is to the output pane of the Command Window.
      do :dUFLP:PapeBin
      or to use a printer other than the default, you would need
      to know the name of the printer:
      cPrinter = "HP LaserJet 1020"
      do :dUFLP:PapeBin with cPrinter

   #define  DC_PAPERNAMES     16
   #define  DC_PAPERS         2
   #define  DC_BINNAMES       12
   #define  DC_BINS           6
   #define  ZEROS(n)          replicate(chr(0), n)
   parameters cDevice

   if not type("argVector(1)") == "C"
       cDevice  := getPrinterDefault()
//       ? cDevice  // moved out of if...endif  MB 2020-08-10
    ? cDevice
   local a, i
   a  =  getBins( cDevice, "")
   for i = 1 to int((a.size + 1) / 2)
       ?     a[i, 2]
       ??    " - "
       ??    a[i, 1]


// return a 2 column array of paper bins for a printerName.
// column 1 = binName <char>,
// column 2 = PapeBin <int>.
function getBins(cDevice, cPort)
    local    aRet, cName, i, ii, lpDevMode, nPair, nWord,;
             sPaperName, sPapeBin
    lpDevMode   =  0
    // get the number of PapeBin/paperName pairs.
    nPair =  RMM_DeviceCapability(;
    if nPair > 0
       // create empty PapeBin buffer of proper length.
       sPapeBin  =  ZEROS(nPair * 2)
       // fill the PapeBin buffer.
       // create empty paperName buffer of proper length.
       sPaperName  =  ZEROS(nPair * 24)
       // fill the paperName buffer.
       // create the return array.
       aRet  =  new array(nPair, 2)
       for i = 0 to nPair - 1
          // loop through and assign the array values.
          // store the PapeBin number into nX.
          nWord =  getWord(sPapeBin, i * 2)
          cName =  ""
          for ii = 0 to 23 //63
             // loop through reading the paperName buffer.
             if sPaperName.getByte((i * 24) + ii) == 0
                // ran into a string terminator.
                // assign ii to exit the loop.
                ii := 24
                // add the character to c.
                cName += chr(sPaperName.getByte( ;
                         (i * 24) + ii))
          // assign the pair to a row in the array.
          aRet[i + 1, 1] =  cName    // paperName.
          aRet[i + 1, 2] =  nWord    // PapeBin.
       aRet  =  new array()
return   aRet

// return the windows default printer as a string.
function getPrinterDefault
    Local sBuff, cRet, nLen
    sBuff =  ZEROS(250)
    nLen  =  RMM_GetWinIniString( ;
             "windows", "device", ;
             ",,,", sBuff, sBuff.length)
    cRet  =  sBuff.left(sBuff.indexOf(","))
return   cRet.rightTrim()

// return a WORD from the string sValu starting at nByte.
function getWord(sValu, nByte)
return   int(sValu.getByte(nByte) + ;
          bitlshift(sValu.getByte(nByte + 1), 8))

function initExterns
    if not type("RMM_DeviceCapability") == "FP"
       extern CINT RMM_DeviceCapability( ;
                winspool.drv from 'DeviceCapabilitiesA'
    if not type("RMM_GetWinIniString") == "FP"
       extern CULONG RMM_GetWinIniString( ;
                kernel32 from "GetProfileStringA"

// end of file: PapeBin.prg