How to select Printer Tray or PaperSource in VB.NET?

Anybody manage to select a printer tray for printing?

                Dim pd As New PrintDocument
                pd.PrinterSettings.PrinterName = strDefaultPrinter

Now I want to enumerate the available printer trays, (say in a combobox), allow the user to set the chosen printer tray and print.

pd.PrinterSettings.PaperSources seems to be readonly?
LVL 1
westerdaleAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

the-edgeCommented:
use
        pd.PrinterSettings.PaperSources
to get the collection of available trays

and
        pd.DefaultPageSettings.PaperSource
to set the tray to use

the edge
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
westerdaleAuthor Commented:
Wow That was quick!

I set the Paper Source as you suggested. However when I check the printer it is still set to the default paper source. Have I done something wrong? (The enumeration worked!


        Dim pd As New PrintDocument
        Dim PSource As System.Drawing.Printing.PaperSource
        Try
            pd.PrinterSettings.PrinterName = strDefaultPrinter

            For Each PSource In pd.PrinterSettings.PaperSources
                If PSource.SourceName = cboTray.Text Then
                    pd.DefaultPageSettings.PaperSource = PSource
                    Exit For
                End If
            Next
        Catch ex As Exception

        End Try

'Now I want to start a process to print something
e.g.
        Dim myProcess As New Process
        Dim startInfo As New ProcessStartInfo("C:\Programme\Adobe\Acrobat 5.0\Reader\AcroRd32.exe")
        startInfo.WindowStyle = ProcessWindowStyle.Minimized
        startInfo.Arguments = "/t """ & txtFilename.Text & """ """ & strDefaultPrinter & """ """ & lblPrinterDriver.Text & """ """ & lblPrinterPort.Text & """"
        'MsgBox(startInfo.Arguments)

        myProcess.Start(startInfo)


0
Bob LearnedCommented:
Setting PaperSource sets it for the PrintDocument, and not for the printer.  So when you run Acrobat Reader, the printer settings haven't changed.
0
Exploring SharePoint 2016

Explore SharePoint 2016, the web-based, collaborative platform that integrates with Microsoft Office to provide intranets, secure document management, and collaboration so you can develop your online and offline capabilities.

westerdaleAuthor Commented:
I can't issue points untill the setting of the papersource issue is solved. There must be a way to set this in the default settings of the printer?

the-edge any suggestions here?
0
Bob LearnedCommented:
I found some code to set the PaperSource from VB6.  It might take a little work to get it to work in VB.NET.  

Are you interested?
0
westerdaleAuthor Commented:
Certainly,

Though if it's: Then it will not work
Firstly. The Printers collection is readyonly
secondly using Printer object does not change the tray. Certainly not globally.
I wrote an activeX dll to test this (bit extreme I know:-)



Dim pr As Printer
    'pr.DeviceName = strPrinterName
   'pr.PaperBin = vbPRBNEnvManual
   
    'Set pr = Nothing
    'For Each pr In Printers
    '    If UCase$(pr.DeviceName) = UCase$(strPrinterName) Then
    '        Set Printer = p
         
    '        pr.PaperBin = vbPRBNEnvManual
    '        Set pr = Nothing
    '        Exit For
    '    End If
    'Next
0
westerdaleAuthor Commented:
Certainly,

Though if it's: Then it will not work
Firstly. The Printers collection is readyonly
secondly using Printer object does not change the tray. Certainly not globally.
I wrote an activeX dll to test this (bit extreme I know:-)



Dim pr As Printer
    'pr.DeviceName = strPrinterName
   'pr.PaperBin = vbPRBNEnvManual
   
    'Set pr = Nothing
    'For Each pr In Printers
    '    If UCase$(pr.DeviceName) = UCase$(strPrinterName) Then
    '        Set Printer = p
         
    '        pr.PaperBin = vbPRBNEnvManual
    '        Set pr = Nothing
    '        Exit For
    '    End If
    'Next
0
Bob LearnedCommented:
In this Micro$oft article it talks about setting the paper source using API calls:

FIX: Cannot Change Page Settings During Print Job
http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/Q180/6/45.asp&NoWebContent=1

You could modify it to fit your needs.
0
westerdaleAuthor Commented:
Thanks. I tried this already
I added the function below into a VB6 class: I tested the class under VB6 and VB.NET
the lngHwnd is the int32 handle from my VB.NEt app as the class does not have a handle

When I checked the Printer settings they appear not to have changed.




Public Function SetPrinterTray(lngHwnd As Long, strPrinterName As String, strPrinterDriverName As String, lngTray As Long) As Long
'vbPRBNUpper    1    Use paper from the upper bin.
'VbPRBNLower    2    Use paper from the lower bin.
'VbPRBNMiddle    3    Use paper from the middle bin.
'VbPRBNManual    4    Wait for manual insertion of each sheet of paper.
'VbPRBNEnvelope    5    Use envelopes from the envelope feeder.
'VbPRBNEnvManual    6    Use envelopes from the envelope feeder, but wait for manual insertion.
'VbPRBNAuto    7    (Default) Use paper from the current default bin.
'VbPRBNTractor    8    Use paper fed from the tractor feeder.
'VbPRBNSmallFmt    9    Use paper from the small paper feeder.
'VbPRBNLargeFmt    10    Use paper from the large paper bin.
'VbPRBNLargeCapacity    11    Use paper from the large capacity feeder.
'VbPRBNCassette    14    Use paper from the attached cassette cartridge.

          Dim di As DOCINFO
          Dim hPrintDc As Long
          Dim Ret As Long
          Dim LastError As Long
          'Dim tx$

          myHandle = lngHwnd 'Sets the handle to the process

          'tx$ = "Hello World!"
          hPrintDc = CreateDC(strPrinterDriverName, strPrinterName, 0, 0)
          di.cbSize = Len(di) ' 20
          'di.lpszDocName = "VB Test Document" ' Optional

          ' Initialize page settings.
          Ret = ResetPrinterDC(Printer.DeviceName, hPrintDc, lngTray, DMORIENT_PORTRAIT)

'          Ret = StartDoc(hPrintDc, di)
'          Ret = StartPage(hPrintDc)
'          Ret = TextOut(hPrintDc, 1000, 1000, tx$, Len(tx$))
'          Ret = EndPage(hPrintDc)

          ' Change page settings.
'          Ret = ResetPrinterDC(Printer.DeviceName, hPrintDc, _
'          DMBIN_LOWER, DMORIENT_LANDSCAPE)
'
'          Ret = StartPage(hPrintDc)
'          Ret = TextOut(hPrintDc, 1000, 1000, tx$, Len(tx$))
'          Ret = EndPage(hPrintDc)
'          Ret = EndDoc(hPrintDc)
          Ret = DeleteDC(hPrintDc)


   

End Function
0
Bob LearnedCommented:
I tested the code in the article in a VB6 form, and it worked just fine.  But it, too, might only set the settings for the application, and not for the Acrobat reader.

Have to keep looking!
0
westerdaleAuthor Commented:
I think the key is the default settings. I even had a peak in the registry though I did not find anything useful.

These settings must be stored somewhere, trick is to find out where. Perhaps this is at the individual driver level? What do you think? I'll be using HP lasers.
0
the-edgeCommented:
maybe this can be useful for you

the edge
0
the-edgeCommented:
sorry missed the link in previoous comment:

http://www.fawcette.com/vsm/2002_02/magazine/columns/desktopdeveloper/

excuse me

the edge
0
westerdaleAuthor Commented:
The edge,

Those links were good especially the merrioncomputing link (this one was a new one for me).

Under Vb.NET
Dim myProcess As New Process
does not produce a valid handle until the myProcess.start is activated (and therefore too late to use the handle in the printer document process (see below).
I see no way to bind a process  (the Acrobat process) to a printer setttings change

Under VB6

 Ret = ResetPrinterDC(lngHwnd, strPrinterDriverName, hPrintDc, lngTray, DMORIENT_PORTRAIT)

     Function ResetPrinterDC(lngHwnd As Long, PrinterName As String, hPrtDc As Long, _
          PaperSource As Long, PaperOrient As Long) As Boolean
          Dim nSize As Long ' Size of DEVMODE
          Dim pDevMode As DEVMODE
          Dim PrinterHandle As Long ' handle to printer
          Dim LastError As Long ' return value for GetLastError
          Dim aDevMode() As Byte ' working DEVMODE

          ' Get a handle to the printer.
          If OpenPrinter(PrinterName, PrinterHandle, 0&) Then
              nSize = DocumentProperties(lngHwnd, PrinterHandle, _
              PrinterName, 0&, 0&, 0)
              ' Reserve memory for the actual size of the DEVMODE
              ReDim aDevMode(1 To nSize)

              ' Fill the DEVMODE from the printer.
              nSize = DocumentProperties(lngHwnd, PrinterHandle, _
              PrinterName, aDevMode(1), 0&, DM_OUT_BUFFER)
              ' Copy the predefined portion of the DEVMODE.
              Call CopyMemory(pDevMode, aDevMode(1), Len(pDevMode))

              ' Change the appropriate member in the DevMode.
              ' In this case, you want to change the paper bin and
              ' orientation.
              pDevMode.dmDefaultSource = PaperSource
              pDevMode.dmOrientation = PaperOrient
              ' Set the dmFields bit flag to indicate what you're changing.
              pDevMode.dmFields = DM_DEFAULTSOURCE Or DM_ORIENTATION

              ' Copy your changes back, then update DEVMODE.
              Call CopyMemory(aDevMode(1), pDevMode, Len(pDevMode))
              nSize = DocumentProperties(lngHwnd, PrinterHandle, _
              PrinterName, aDevMode(1), aDevMode(1), _
              DM_IN_BUFFER Or DM_OUT_BUFFER)

              nSize = ResetDC(hPrtDc, aDevMode(1)) ' Reset the DEVMODE

              ' Close the handle when you're done with it.
              ClosePrinter (PrinterHandle)
              ResetPrinterDC = True ' Reset succeeded!
          Else
              ResetPrinterDC = False ' Reset failed!
              LastError = GetLastError()
              MsgBox "Error changing Page settings. Error Code: " _
              & LastError, vbExclamation, "Print Error"
          End If
      End Function

Would be the way to go using the lngHwnd to bind to the process..
I thought to ShellExecute or CreateProcessA , but here the handle is 'too late' to be used to change the printer settings

So to me the only way to change the printer tray is to employ a knome to do it ;-)

Lastly I would like to issue points even though my question is not complete (you have really helped me with ideas) what is the protocol here?

0
Bob LearnedCommented:
If you feel that only one person's answers helped you, then accept one of their comments as an Answer.  If you feel that both were helpful, then you can split the points between the two.
0
westerdaleAuthor Commented:
Thanks TheLearnedOne and The Edge

Maybe someone will find this useful. An undocmented feature that allows you to send PDFs to any printer on the fly. Though sadly, only to the default tray.


Dim myProcess As New Process
 Dim startInfo As New ProcessStartInfo("C:\Programme\Adobe\Acrobat 5.0\Reader\AcroRd32.exe")
            startInfo.WindowStyle = ProcessWindowStyle.Normal
            startInfo.Arguments = "/t """ & txtFilename.Text & """ """ & straPrinterName & """ """ & lblPrinterDriver.Text & """ """ & lblPrinterPort.Text & """"
            myProcess.Start(startInfo)


To get the Printer driver...
  Dim regKey As RegistryKey
 Dim keyValue As String

                        keyValue = "Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers\\" & strDefaultPrinter
                        regKey = Registry.LocalMachine.OpenSubKey(keyValue, False)
                        lblPrinterDriver.Text = regKey.GetValue("Printer Driver", 0)
                        lblPrinterPort.Text = regKey.GetValue("Port", 0)
                        regKey.Close()





0
kavvisCommented:
I reade this answear many times right now.

What did you come up to? "Though sadly, only to the default tray."
So you can´t write to tray 3 for exemple? only the default tray? It´s seems verry strange... ?
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
.NET Programming

From novice to tech pro — start learning today.