Link to home
Start Free TrialLog in
Avatar of kerzner
kerznerFlag for United States of America

asked on

Change printer tray from vb

Hi all,

I'm looking for a solution to do the following:

I have an ActiveX control, and the only thing this control does is to print a given html page (by url). To do this job, I'm using the WebBrowser control, with code like

IE.ExecWB OLECMDID_PRINT, OLECMDEXECOPT_DONTPROMPTUSER

Now the problem is that I would like (or, better to say, the clients would like;)) to select the exact printer tray to use.

What I see as a solution would be to find the default printer, and set its (imaginary) DefaultTray property to X, then to call the IE print function.

What do you think?

Thanks,
Lazar
Avatar of EDDYKT
EDDYKT
Flag of Canada image

Avatar of kerzner

ASKER

Well, this works if you want to use the Printer object, and print something with it; however it does not affect the WebBrowser component's print function. What I'm looking for is maybe to change (and save!) the default printer's PaperBin before asking the WebBrowser to print.
Avatar of kerzner

ASKER

Well, I used the code from this page, and it worked perfectly!!!

http://support.microsoft.com/default.aspx?scid=kb;EN-US;180645
Avatar of kerzner

ASKER

OK I will give the points to the first one who read this and submits any comment
:D
you can delete the question by posting your comment here

https://www.experts-exchange.com/Community_Support/
Avatar of kerzner

ASKER

Thanks, I just did that.
Was looking for a delete/cancel button or something, but there wasn't such thing and I decided it's impossible to cancel a question.
Avatar of kerzner

ASKER

If one's curious of the code, here it is:
(It is compiled from several places, and can be used to permanently change printer settings, in my case Paper Orientation, but can be used for a wide range of other properties)


---------------------------------------------

Option Explicit

' Constants for DeviceCapabilities
Private Const DC_BINS = 6
Private Const DC_BINNAMES = 12

' Printer Access Levels
Private Const PRINTER_ACCESS_ADMINISTER As Long = &H4
Private Const PRINTER_ACCESS_USE As Long = &H8
Private Const STANDARD_RIGHTS_REQUIRED As Long = &HF0000
Private Const PRINTER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED Or PRINTER_ACCESS_ADMINISTER Or PRINTER_ACCESS_USE)
 
' Constants for DEVMODE.
Private Const CCHDEVICENAME = 32
Private Const CCHFORMNAME = 32

' Constants for DocumentProperties() call.
Private Const DM_MODIFY = 8
Private Const DM_IN_BUFFER = DM_MODIFY
Private Const DM_COPY = 2
Private Const DM_OUT_BUFFER = DM_COPY

' Constants for Orientation.
Private Const DMORIENT_PORTRAIT = 1
Private Const DMORIENT_LANDSCAPE = 2

' Constants for printer bin.
Private Const DMBIN_UPPER = 1
Private Const DMBIN_LOWER = 2

' Constants for DMFIELDS (which fields did you change?).
Private Const DM_ORIENTATION = &H1
Private Const DM_DEFAULTSOURCE = &H200

Private Type DOCINFO
   cbSize As Long
   lpszDocName As String
   lpszOutput As String
End Type

Private Type PRINTER_DEFAULTS
   pDataType As String
   pDevMode As Long
   DesiredAccess As Long
End Type

Private Type PRINTER_INFO_2
   pServerName As Long
   pPrinterName As Long
   pShareName As Long
   pPortName As Long
   pDriverName As Long
   pComment As Long
   pLocation As Long
   pDevMode As Long
   pSepFile As Long
   pPrintProcessor As Long
   pDataType As Long
   pParameters As Long
   pSecurityDescriptor As Long
   Attributes As Long
   Priority As Long
   DefaultPriority As Long
   StartTime As Long
   UntilTime As Long
   Status As Long
   cJobs As Long
   AveragePPM As Long
End Type

Private Type DEVMODE
   dmDeviceName(1 To CCHDEVICENAME) As Byte
   dmSpecVersion As Integer
   dmDriverVersion As Integer
   dmSize As Integer
   dmDriverExtra As Integer
   dmFields As Long
   dmOrientation As Integer
   dmPaperSize As Integer
   dmPaperLength As Integer
   dmPaperWidth As Integer
   dmScale As Integer
   dmCopies As Integer
   dmDefaultSource As Integer
   dmPrintQuality As Integer
   dmColor As Integer
   dmDuplex As Integer
   dmYResolution As Integer
   dmTTOption As Integer
   dmCollate As Integer
   dmFormName(1 To CCHFORMNAME) As Byte
   dmUnusedPadding As Integer
   dmBitsPerPel As Integer
   dmPelsWidth As Long
   dmPelsHeight As Long
   dmDisplayFlags As Long
   dmDisplayFrequency As Long
End Type

Private Declare Function OpenPrinter Lib "winspool.drv" Alias _
    "OpenPrinterA" (ByVal pPrinterName As String, phPrinter As _
    Long, pDefault As Any) As Long

Private Declare Function ClosePrinter Lib "winspool.drv" _
    (ByVal hPrinter As Long) As Long

Private Declare Function GetPrinter Lib "winspool.drv" Alias _
    "GetPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, _
   pPrinter As Any, ByVal cbBuf As Long, pcbNeeded As Long) As Long
 
Private Declare Function SetPrinter Lib "winspool.drv" Alias _
   "SetPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, _
   pPrinter As Any, ByVal Command As Long) As Long
 
Private Declare Function DocumentProperties Lib "winspool.drv" _
    Alias "DocumentPropertiesA" (ByVal hwnd As Long, _
    ByVal hPrinter As Long, ByVal pDeviceName As String, _
    pDevModeOutput As Any, pDevModeInput As Any, _
    ByVal fMode As Long) As Long

Private Declare Function ResetDC Lib "gdi32" Alias "ResetDCA" _
    (ByVal hdc As Long, lpInitData As Any) As Long

Private Declare Function CreateDC Lib "gdi32" Alias "CreateDCA" _
    (ByVal lpDriverName As String, ByVal lpDeviceName As String, _
    ByVal lpOutput As Long, ByVal lpInitData As Long) As Long

Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) _
    As Long

Private Declare Function GetLastError Lib "KERNEL32" () As Long

Private Declare Sub CopyMemory Lib "KERNEL32" Alias "RtlMoveMemory" _
    (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)

Function SetPrinterPageSource(PrinterName As String, hPrtDc As Long, PaperSource As Long) As Boolean

   Dim nSize As Long           ' Size of array (used when reading DEVMODE and PRINTER_INFO_2)
   Dim pPrinterInfo2 As PRINTER_INFO_2 ' PRINTER_INFO_2 structure
   Dim pDevMode As DEVMODE             ' DEVMODE structure
   Dim hPrinter As Long        ' Handle to the printer
   Dim LastError As Long       ' Return value for GetLastError
   Dim bPrinterInfo2() As Byte ' The PRINTER_INFO_2 structure in binary format
   Dim bDevMode() As Byte      ' The DEVMODE structure in binary format

   Dim pd As PRINTER_DEFAULTS
   pd.DesiredAccess = PRINTER_ALL_ACCESS
   
   ' Get a handle to the printer with full access - needed if we want to save our changes permanently
   If OpenPrinter(PrinterName, hPrinter, pd) Then

      ' Read PRINTER_INFO_2 as binary array
      GetPrinter hPrinter, 2&, 0&, 0&, nSize
      ReDim bPrinterInfo2(1 To nSize) As Byte
      GetPrinter hPrinter, 2, bPrinterInfo2(1), nSize, nSize
     
      ' Fill in the structure
      CopyMemory pPrinterInfo2, bPrinterInfo2(1), Len(pPrinterInfo2)

      ' Get the size of the DEVMODE, passing 0's at the end
      nSize = DocumentProperties(Me.hwnd, hPrinter, PrinterName, 0&, 0&, 0)

      ' Reserve memory for the actual size of the DEVMODE
      ReDim bDevMode(1 To nSize)

      ' Fill the DEVMODE as binary array
      DocumentProperties Me.hwnd, hPrinter, PrinterName, bDevMode(1), 0&, DM_OUT_BUFFER

      ' Copy the predefined portion of the DEVMODE.
      CopyMemory pDevMode, bDevMode(1), Len(pDevMode)

      ' Change the appropriate member in the DevMode.
      'pDevMode.dmDefaultSource = PaperSource
      pDevMode.dmOrientation = DMORIENT_LANDSCAPE

      ' Set the dmFields bit flag to indicate what you're changing.
      'pDevMode.dmFields = pDevMode.dmFields Or DM_DEFAULTSOURCE
      pDevMode.dmFields = pDevMode.dmFields Or DM_ORIENTATION

      ' Copy your changes back, then update DEVMODE.
      CopyMemory bDevMode(1), pDevMode, Len(pDevMode)
      DocumentProperties Me.hwnd, hPrinter, PrinterName, bDevMode(1), bDevMode(1), DM_IN_BUFFER Or DM_OUT_BUFFER

      ' Point PRINTER_INFO_2 at our modified DEVMODE
      pPrinterInfo2.pDevMode = VarPtr(bDevMode(1))
     
      ' Finally make our changes permanent
      SetPrinter hPrinter, 2, pPrinterInfo2, 0&
     
      ResetDC hPrtDc, bDevMode(1)   ' Reset the DEVMODE
   
      ' Close the handle when you're done with it.
      ClosePrinter hPrinter
      SetPrinterPageSource = True

   Else
   
      SetPrinterPageSource = False  ' Reset failed!
      LastError = GetLastError()
      MsgBox "Error setting printer bin. Error Code: " & LastError, vbExclamation, "Print Error"
     
   End If
   
End Function
Avatar of kerzner

ASKER

Oh, and to use the above routine, try for example

   Dim hPrintDC As Long: hPrintDC = CreateDC(Printer.DriverName, Printer.DeviceName, 0, 0)
   SetPrinterPageSource Printer.DeviceName, hPrintDC, SomeTrayNumber

you can get the tray/bin numbers for a printer by the following routine:

' Pass this to a multiline textbox...
Private Function GetPrinterBins(Prn As Printer) As String
   Dim PrinterBins As String
   Dim BinsCount As Long: BinsCount = DeviceCapabilities(Prn.DeviceName, Prn.Port, DC_BINS, ByVal vbNullString, 0)
   Dim BinNumbers() As Integer: ReDim BinNumbers(1 To BinsCount)
   Dim BinNames As String: BinNames = String(24 * BinsCount, 0)
   BinsCount = DeviceCapabilities(Prn.DeviceName, Prn.Port, DC_BINS, BinNumbers(1), 0)
   BinsCount = DeviceCapabilities(Prn.DeviceName, Prn.Port, DC_BINNAMES, ByVal BinNames, 0)
   PrinterBins = PrinterBins & Prn.DeviceName
   Dim BinString As String
   Dim nBin As Integer
   For nBin = 1 To BinsCount
      BinString = Mid(BinNames, 24 * (nBin - 1) + 1, 24)
      BinString = Left(BinString, InStr(1, BinString, Chr(0)) - 1)
      BinString = String(6 - Len(CStr(BinNumbers(nBin))), " ") & BinNumbers(nBin) & "  " & BinString
      PrinterBins = PrinterBins & vbCrLf & BinString
   Next
   GetPrinterBins = PrinterBins
End Function


where DeviceCapabilities is declared with:

Private Declare Function DeviceCapabilities Lib "winspool.drv" _
   Alias "DeviceCapabilitiesA" (ByVal lpDeviceName As String, _
   ByVal lpPort As String, ByVal iIndex As Long, lpOutput As Any, _
   ByVal dev As Long) As Long

-----------------------------

Cheerz!

Lazar
ASKER CERTIFIED SOLUTION
Avatar of GranMod
GranMod

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial