Solved

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

Posted on 2003-10-30
18
14,133 Views
Last Modified: 2011-10-26
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?
0
Comment
Question by:westerdale
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 5
  • 4
  • +1
18 Comments
 
LVL 3

Accepted Solution

by:
the-edge earned 150 total points
ID: 9650481
use
        pd.PrinterSettings.PaperSources
to get the collection of available trays

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

the edge
0
 
LVL 1

Author Comment

by:westerdale
ID: 9650918
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
 
LVL 96

Assisted Solution

by:Bob Learned
Bob Learned earned 350 total points
ID: 9653242
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
How Do You Stack Up Against Your Peers?

With today’s modern enterprise so dependent on digital infrastructures, the impact of major incidents has increased dramatically. Grab the report now to gain insight into how your organization ranks against your peers and learn best-in-class strategies to resolve incidents.

 
LVL 1

Author Comment

by:westerdale
ID: 9655712
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
 
LVL 96

Expert Comment

by:Bob Learned
ID: 9657822
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
 
LVL 1

Author Comment

by:westerdale
ID: 9657891
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
 
LVL 1

Author Comment

by:westerdale
ID: 9657892
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
 
LVL 96

Assisted Solution

by:Bob Learned
Bob Learned earned 350 total points
ID: 9657914
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
 
LVL 1

Author Comment

by:westerdale
ID: 9658021
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
 
LVL 96

Expert Comment

by:Bob Learned
ID: 9658054
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
 
LVL 1

Author Comment

by:westerdale
ID: 9658150
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
 
LVL 3

Expert Comment

by:the-edge
ID: 9658924
maybe this can be useful for you

the edge
0
 
LVL 3

Assisted Solution

by:the-edge
the-edge earned 150 total points
ID: 9659085
0
 
LVL 3

Expert Comment

by:the-edge
ID: 9659098
sorry missed the link in previoous comment:

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

excuse me

the edge
0
 
LVL 1

Author Comment

by:westerdale
ID: 9670696
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
 
LVL 96

Expert Comment

by:Bob Learned
ID: 9670736
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
 
LVL 1

Author Comment

by:westerdale
ID: 9670879
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
 

Expert Comment

by:kavvis
ID: 37030941
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

Featured Post

More Than Just A Video Library

Train for your certification. Learn the latest DevOps tools. Grow your skillset to do better work.

At Linux Academy, we release new training modules every week so you'll always be up to date on the latest tech.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

IP addresses can be stored in a database in any of several ways.  These ways may vary based on the volume of the data.  I was dealing with quite a large amount of data for user authentication purpose, and needed a way to minimize the storage.   …
This document covers how to connect to SQL Server and browse its contents.  It is meant for those new to Visual Studio and/or working with Microsoft SQL Server.  It is not a guide to building SQL Server database connections in your code.  This is mo…
This video Micro Tutorial shows how to password-protect PDF files with free software. Many software products can do this, such as Adobe Acrobat (but not Adobe Reader), Nuance PaperPort, and Nuance Power PDF, but they are not free products. This vide…
In this video, viewers will be given step by step instructions on adjusting mouse, pointer and cursor visibility in Microsoft Windows 10. The video seeks to educate those who are struggling with the new Windows 10 Graphical User Interface. Change Cu…

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question