Get the available paper bins from a printer


Sometimes you might want to find out how many paper bins a printer has. (Thanks to Barbara P for original question, code.)


 


 


 


lcPrinterName = GETPRINTER()


nPrinters=APRINTERS(laAvailPrinters)


FOR i = 1 TO nPrinters


      IF UPPER(laAvailPrinters[i,1]) = UPPER(lcPrinterName)


            lcPort = laAvailPrinters[i,2]


            lcPort = CHRTRAN(lcPort,’:’,”)


            EXIT


      ENDIF


ENDFOR


?”lcPort”,lcPort


?”lcPrinterName”,lcPrinterName


 


#define DC_BINS             6


#define DC_BINNAMES         12


DECLARE INTEGER DeviceCapabilities IN winspool.drv;


      STRING pDevice, STRING pPort, INTEGER fwCapability,;


      STRING @pOutput, INTEGER pDevMode


 


DECLARE INTEGER GetLastError IN kernel32


 


nResult= DeviceCapabilities(lcPrinterName, lcPort, DC_BINS, 0, 0)


IF nResult=-1


      ?”Err getting DC_BINS size”,GetLastError()


      RETURN


ENDIF


?nResult


cstr=SPACE(nResult* 2)  && WORD is 2 bytes each


nResult=DeviceCapabilities(lcPrinterName, lcPort, DC_BINS, @cstr, 0)


IF nResult=-1


      ?     “Err getting DC_BINS”,GetLastError()


ENDIF


nBins=nResult


?”Bins”


DIMENSION aBins[nBins]


FOR i = 1 TO nBins


      aBins[i]=CTOBIN(SUBSTR(cstr,i*21,2),”2rs”)


      ?aBins[i]


ENDFOR


 


cstr=SPACE(nBins*24)


nResult=DeviceCapabilities(lcPrinterName, lcPort, DC_BINNAMES, @cstr, 0)


IF nResult=-1


      ?     “Err getting DC_BINNAMES”,GetLastError()


ENDIF


FOR i = 1 TO nBins


      ?CHRTRAN(SUBSTR(cstr,(i-1)*24+1,24),CHR(0),””)


ENDFOR


 


 


 

Comments (5)

  1. Tracy Holzer says:

    I was fortunate to receive assistance from Yuri Rubinov and Simon Clark back in July 2003 on this. They developed some handy code for viewing all papertrays on all printers you may find useful:

    <PRE>

    * Courtesy Simon Clark and Yuri Rubinov, Universal Thread July 2003

    * Thread #808875 Message #815017

    * put a DEFAULTSOURCE=<bin number> in the EXPR column

    * of the FRX row with OBJTYPE=53 after selection

    oform=CREATEOBJECT(‘papertrayform’)

    oform.SHOW()

    READ EVENTS

    RETURN

    DEFINE CLASS papertrayform AS FORM

    TOP = 0

    LEFT = 1

    HEIGHT = 365

    WIDTH = 631

    DOCREATE = .T.

    CAPTION = "Paper Tray Selection Form"

    NAME = "PAPERTRAYS"

    DIMENSION paperbins[1,4]

    ADD OBJECT list1 AS LISTBOX WITH ;

    FONTNAME = "Courier New", ;

    FONTSIZE = 9, ;

    BOUNDCOLUMN = 1, ;

    ROWSOURCETYPE = 6, ;

    ROWSOURCE=”,;

    CONTROLSOURCE = "m.selection", ;

    HEIGHT = 300, ;

    COLUMNLINES = .T., ;

    LEFT = 8, ;

    MULTISELECT = .F., ;

    TABINDEX = 10, ;

    TOP = 39, ;

    WIDTH = 612, ;

    NAME = "List1"

    ADD OBJECT label1 AS LABEL WITH ;

    CAPTION = "Press <ENTER> to select a paper tray";

    +"or Double-Click on any item to select it", ;

    HEIGHT = 17, ;

    LEFT = 8, ;

    TOP = 11, ;

    WIDTH = 580, ;

    NAME = "Label1"

    PROCEDURE buf2word

    *PROCEDURE buf2word && Convert BUF to WORD

    PARAMETERS QQbuffer

    * —INTERFACE—

    PRIVATE ALL LIKE QQ*

    * IMPORTS:

    * A buffer/pointer

    *

    * EXPORTS:

    * The passed in buffer converted to a word format

    *

    * —INITIALISE—

    QQudfRet = ASC(SUBSTR(QQbuffer, 1,1)) + ASC(SUBSTR(QQbuffer, 2,1)) * 256

    RETURN QQudfRet

    ENDPROC

    PROCEDURE INIT

    IF USED(‘trays’)

    USE IN trays

    ENDIF

    IF FILE(‘trays.dbf’)

    DELETE FILE trays.DBF

    ENDIF

    CLEAR

    DODEFAULT()

    SET SAFETY OFF

    *For the FRX’s it easy, you just put a

    *DEFAULTSOURCE=<bin number> in the EXPR column

    *of the FRX row with OBJTYPE=53 (same for DUPLEX= by the way…).

    #DEFINE GMEM_FIXED 0

    #DEFINE DC_PAPERS 2

    #DEFINE DC_BINS 6

    #DEFINE DC_SIZE 8

    #DEFINE DC_VERSION 10

    #DEFINE DC_BINNAMES 12

    #DEFINE DC_PAPERNAMES 16

    #DEFINE DEFAULT_VALUES 0

    * Needed to interrogate the printer driver for paper bins/trays

    DECLARE INTEGER DeviceCapabilities IN winspool.drv;

    STRING pDevice, STRING pPort, INTEGER fwCapability,;

    STRING @pOutput, INTEGER pDevMode

    =APRINTERS(pPrinters)

    FOR ip = 1 TO ALEN(pPrinters,1)

    *QQprintername=SET("PRINTER",2) && windows own default printer

    QQprintername=pPrinters(ip,1)

    pPort=ALLTRIM(pPrinters(ip,2))

    * Windows API declarations

    * Hook in here to determine the paper trays and their bin numbers

    QQbinBfr = REPLICATE(CHR(0), 16384)

    QQbinBf2 = REPLICATE(CHR(0), 1024)

    * provide valid printer and port names

    QQnCount = DeviceCapabilities(QQprintername, pPort, DC_BINNAMES, @QQbinBfr, 0)

    QQnCnt2 = DeviceCapabilities(QQprintername, pPort, DC_BINS, @QQbinBf2, 0)

    * Set the number of bins available on this printer property

    p_bin_count=IIF(QQnCount<0, 0, QQnCount)

    IF p_bin_count>0

    * each string buffer is 24 characters long, terminated with a NULL / chr(0)

    * and contains the name of a paper bin

    DIMENSION p_bin_names[QQnCount], p_bin_labels[QQnCount]

    FOR QQindex=1 TO QQnCount

    QQbinName = SUBSTR(QQbinBfr, (QQindex-1)*24+1, 24) + CHR(0)

    QQbinName = SUBSTR(QQbinName, 1, AT(CHR(0), QQbinName)-1)

    p_bin_names[QQindex] = QQbinName

    ENDFOR

    QQptr = 1

    FOR QQindex=1 TO QQnCnt2*2 STEP 2

    QQbinNum = THISFORM.buf2word(SUBSTR(QQbinBf2, QQindex, 2))

    p_bin_labels[QQptr] = QQbinNum

    QQptr = QQptr + 1

    ENDFOR

    ENDIF

    IF ALEN(p_bin_names,1)=ALEN(p_bin_labels,1)

    FOR i = 1 TO ALEN(p_bin_names,1)

    IF TYPE(‘thisform.paperbins’)="U"

    DIMENSION THISFORM.paperbins(i,4)

    ELSE

    DIMENSION THISFORM.paperbins(ALEN(THISFORM.paperbins,1)+1,4)

    ENDIF

    THISFORM.paperbins(ALEN(THISFORM.paperbins,1),1)=QQprintername

    THISFORM.paperbins(ALEN(THISFORM.paperbins,1),2)=p_bin_names(i)

    THISFORM.paperbins(ALEN(THISFORM.paperbins,1),3)=p_bin_labels(i)

    THISFORM.paperbins(ALEN(THISFORM.paperbins,1),4)=pPort

    ENDFOR

    ENDIF

    ENDFOR

    nlen1=0

    nlen2=0

    nlen3=4

    nlen4=0

    =ACOPY(THISFORM.paperbins,paperbins)

    FOR i = 1 TO ALEN(paperbins,1)

    IF TYPE(‘paperbins(i,1)’)<>"L"

    IF LEN(ALLTRIM(paperbins(i,1)))>nlen1

    nlen1=LEN(ALLTRIM(paperbins(i,1)))

    ENDIF

    ENDIF

    IF TYPE(‘paperbins(i,2)’)<>"L"

    IF LEN(ALLTRIM(paperbins(i,2)))>nlen2

    nlen2=LEN(ALLTRIM(paperbins(i,2)))

    ENDIF

    ENDIF

    IF TYPE(‘paperbins(i,4)’)<>"L"

    IF LEN(ALLTRIM(paperbins(i,4)))>nlen4

    nlen4=LEN(ALLTRIM(paperbins(i,4)))

    ENDIF

    ENDIF

    ENDFOR

    IF nlen1=0

    nlen1=1

    ENDIF

    IF nlen2=0

    nlen2=1

    ENDIF

    IF nlen4=0

    nlen4=1

    ENDIF

    CREATE CURSOR trays (pname c(nlen1),;

    pbin c(nlen2), pbinno c(nlen3), pPort c(nlen4))

    SELE trays

    FOR i = 1 TO ALEN(paperbins,1)

    IF TYPE(‘paperbins(i,1)’)<>"L"

    SELE trays

    APPEND BLANK

    *!* The below will only display the printer name once instead of in

    *!* every row, but capturing the printername would have to be

    *!* changed then on selection in the listbox since that field maybe

    *!* blank

    *!* IF i > 1

    *!* ta=i-1

    *!* IF TYPE(‘paperbins(i,1)’)=TYPE(‘paperbins(ta,1)’) ;

    *!* .and. paperbins(i,1) <> paperbins(ta,1)

    *!* REPLACE trays.pname WITH ALLTRIM(paperbins(i,1))

    *!* ELSE

    *!* IF TYPE(‘paperbins(i,1)’)!=TYPE(‘paperbins(ta,1)’)

    *!* REPLACE trays.pname WITH ALLTRIM(paperbins(i,1))

    *!* ENDIF

    *!* ENDIF

    *!* ENDIF

    REPLACE trays.pname WITH ALLTRIM(paperbins(i,1))

    IF TYPE(‘paperbins(i,2)’)<>"L"

    REPLACE trays.pbin WITH ALLTRIM(paperbins(i,2))

    ENDIF

    IF TYPE(‘paperbins(i,3)’)<>"L"

    REPLACE trays.pbinno WITH ALLTRIM(STR(paperbins(i,3)))

    ENDIF

    IF TYPE(‘paperbins(i,4)’)<>"L"

    REPLACE trays.pPort WITH ALLTRIM(paperbins(i,4))

    ENDIF

    ENDIF

    ENDFOR

    GO TOP

    THISFORM.list1.ROWSOURCE = ‘LEFT(trays.pname,45)+" ";

    +left(trays.pbin,20)+" "+LEFT(trays.pbinno,20)+" ";

    +LEFT(trays.pport,10)’

    THISFORM.list1.REFRESH

    ENDPROC

    PROCEDURE RELEASE

    DODEFAULT()

    ENDPROC

    PROCEDURE UNLOAD

    IF USED(‘TRAYS’)

    USE IN trays

    ENDIF

    CLEAR EVENTS

    DODEFAULT()

    ENDPROC

    PROCEDURE list1.DBLCLICK

    IF USED(‘TRAYS’) .AND. RECCOUNT(‘TRAYS’)>0 .AND. !EOF(‘TRAYS’)

    mchoice=trays.pbinno

    ENDIF

    MESSAGEBOX(‘You chose: ‘+CHR(13)+CHR(13);

    +"Printer: "+ALLTRIM(trays.pname)+ CHR(13);

    +"Tray: "+trays.pbin+CHR(13);

    +"Bin No: "+trays.pbinno+CHR(13),0,’Paper Tray Selectioin’)

    NODEFAULT

    THISFORM.RELEASE()

    ENDPROC

    PROCEDURE list1.KEYPRESS

    LPARAMETERS nKeyCode, nShiftAltCtrl

    IF LASTKEY() = 13 .OR. LASTKEY() = -9

    nKeyCode = 13

    nShiftAltCtrl = 0

    ENDIF

    mchoice=""

    DO CASE

    CASE nKeyCode = 13 .OR. nKeyCode = -9

    IF USED(‘TRAYS’) .AND. RECCOUNT(‘TRAYS’)>0 .AND. !EOF(‘TRAYS’)

    mchoice=trays.pbinno

    ENDIF

    MESSAGEBOX(‘You chose: ‘+CHR(13)+CHR(13);

    +"Printer: "+ALLTRIM(trays.pname)+ CHR(13);

    +"Tray: "+trays.pbin+CHR(13);

    +"Bin No: "+trays.pbinno+CHR(13),0,’Paper Tray Selectioin’)

    NODEFAULT

    THISFORM.RELEASE()

    OTHERWISE

    mchoice=""

    DODEFAULT()

    ENDCASE

    ENDPROC

    PROCEDURE list1.REFRESH

    IF !USED(‘trays’) .OR. RECCOUNT(‘trays’)=0

    THIS.ENABLED=.F.

    ELSE

    THIS.ENABLED=.T.

    ENDIF

    DODEFAULT()

    ENDPROC

    ENDDEFINE

    </PRE>

  2. weberrp says:

    Hi Calvin,

    I have searched high and low for a very simple solution to my printing problem with no good answer.

    platform(s):

    Windows Xp Pro

    MS VFP 9.0 SP1

    HP LJ 4050TN & HP LJ 4350 DTNSL

    History:

    Existing MS VFP 6.0 program produced (printed) Avery # 5960 (3×10) labels from tray 2 and certificates (5" x 8") from Tray 1 and letterhead from Tray 3 while all other print output went to Tray 4 (plain paper).

    Problem:

    After recent upgrade from VFP 6.0 to VFP 9.0 SP1 now the print output always goes to Tray 4 (plain paper). I have resaved each .frx and .lbx with what I think to be the appropriate settings, including the tray selection, but output still goes to Tray 4.

    Question:

    There must be a very simple solution (like SET REPORT BEHAVIOUR  or  SET ENGINE BEHAVIOUR) since the only change was the VFP version on the PCs and no printer changes. I’ve seen various solutions involving classes and pages of code but it just can’t be that complicated can it?  Any help will be greatly appreciated.

    RPWeber

  3. Calvin_Hsia says:

    Hi RPWeber:

    From VFP team member Richard:

    I think that property is removed when the “Print Environment” option is unchecked on the FRX. This is because the tray information is printer specific, so the option wouldn’t work unless the report is always run on the same printer type.

    However, the paper tray setting can be stored as an option in the EXPR field on the first record of the FRX. They can update the EXPR field to have a DEFAULTSOURCE property that specifies which bin to use, the actual values depend on the printer. (For example the one on our floor has a value like this DEFAULTSOURCE=258)

    As long a TAG and TAG2 are empty, the report will use the default printer and attempt to set the properties on the printer to the ones set in EXPR.

  4. jyner_ad says:

    <a href= http://index5.hvo-rost.ru >����� ���</a> <a href= http://index4.hvo-rost.ru >���������� ���� ���������</a> <a href= http://index3.hvo-rost.ru >������� ������� ����������� ����</a> <a href= http://index2.hvo-rost.ru >������� ��� ��������</a> <a href= http://index1.hvo-rost.ru >�������� ���������� �����</a>

  5. Swarnava says:

    thanks Calvin.This code helped me a lot..