Need help on setting printer orientation

rangasamy_v

New member
Joined
Aug 30, 2010
Messages
3
Programming Experience
5-10
Hi,

I try to change some printer settings using the win32 api OpenPrinter,
GetPrinter and SetPrinter in VB.Net application.I copied most of the code from this or
related newsgroups. However, OpenPrinter, GetPrinter and ClosePrinter
works so far but I cannot change the printer settings. SetPrinter
returns the error code ACCESS DENIED. I know I have to deal with the
desired access mask in the _DEFAULT_PRINTER structure when calling
OpenPrinter. Unfortunaltely the declaration of the DEFAULT_PRINTER
structure or class I found on the internet doesn't work with the
OpenPrinter function.

VB.NET:
  Public Structure DEVMODE
        Public dmDeviceName As String
        Dim dmSpecVersion As Short
        Dim dmDriverVersion As Short
        Dim dmSize As Short
        Dim dmDriverExtra As Short
        Dim dmFields As Integer
        Dim dmOrientation As Short
        Dim dmPaperSize As Short
        Dim dmPaperLength As Short
        Dim dmPaperWidth As Short
        Dim dmScale As Short
        Dim dmCopies As Short
        Dim dmDefaultSource As Short
        Dim dmPrintQuality As Short
        Dim dmColor As Short
        Dim dmDuplex As Short
        Dim dmYResolution As Short
        Dim dmTTOption As Short
        Dim dmCollate As Short
        Public dmFormName As String
        Dim dmUnusedPadding As Short
        Dim dmBitsPerPel As Short
        Dim dmPelsWidth As Integer
        Dim dmPelsHeight As Integer
        Dim dmDisplayFlags As Integer
        Dim dmDisplayFrequency As Integer
    End Structure

    Private Structure PRINTER_INFO_2
        Dim pServerName As Integer
        Dim pPrinterName As Integer
        Dim pShareName As Integer
        Dim pPortName As Integer
        Dim pDriverName As Integer
        Dim pComment As Integer
        Dim pLocation As Integer
        Dim pDevMode As IntPtr
        Dim pSepFile As Integer
        Dim pPrintProcessor As Integer
        Dim pDatatype As Integer
        Dim pParameters As Integer
        Dim pSecurityDescriptor As Integer
        Dim Attributes As Integer
        Dim Priority As Integer
        Dim DefaultPriority As Integer
        Dim starttime As Integer
        Dim UntilTime As Integer
        Dim Status As Integer
        Dim cJobs As Integer
        Dim AveragePPM As Integer
    End Structure

    Public Structure PRINTER_DEFAULTS
        Dim pDatatype As Long
        Dim pDevMode As DEVMODE
        Dim DesiredAccess As Long
    End Structure

    Public Structure PRINTER_INFO_5
        Dim pPrinterName As String
        Dim pPortName As String
        Dim Attributes As Integer
        Dim DeviceNotSelectedTimeout As Integer
        Dim TransmissionRetryTimeout As Integer
    End Structure

    'New enumerations for orientation change

    Public Enum PrinterOrientationConstants
        OrientPortrait = 1
        OrientLandscape = 2
    End Enum

    Private Const DM_IN_BUFFER As Integer = 8
    Private Const DM_OUT_BUFFER As Integer = 2
    Private Const DM_ORIENTATION As Integer = &H1S

    Public Const PRINTER_ACCESS_ADMINISTER = &H4
    Public Const PRINTER_ACCESS_USE = &H8
    Public Const STANDARD_RIGHTS_REQUIRED = &HF0000
    Public Const PRINTER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED Or PRINTER_ACCESS_ADMINISTER Or PRINTER_ACCESS_USE)

    'Public Declare Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" (ByVal pPrinterName As String, ByRef phPrinter As IntPtr, ByVal pDefault As Integer) As Long
    Public Declare Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" (ByVal pPrinterName As String, ByRef phPrinter As IntPtr, ByRef pDefault As PRINTER_DEFAULTS) As Long
    Declare Auto Function GetPrinter Lib "winspool.drv" Alias "GetPrinterA" (ByVal hPrinter As IntPtr, ByVal Level As Integer, ByVal pPrinter As IntPtr, ByVal cbBuf As Integer, ByRef pcbNeeded As Integer) As Boolean
    Public Declare Function SetPrinter Lib "winspool.drv" Alias "SetPrinterA" (ByVal hPrinter As IntPtr, ByVal ByValdwLevel As Int32, ByVal pPrinter As IntPtr, ByVal dwCommand As Int32) As Boolean
    Private Declare Function ClosePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long

    Private Declare Function DocumentProperties Lib "winspool.drv" Alias "DocumentPropertiesA" (ByVal hWnd As IntPtr, ByVal hPrinter As IntPtr, ByVal pDeviceName As String, ByRef pDevModeOutput As IntPtr, ByRef pDevModeInput As IntPtr, ByVal fMode As IntPtr) As Integer

    Private Const ERROR_INSUFFICIENT_BUFFER = 122

 Private Sub SetOrientaion()
        Dim sPrnName As String
        Dim hPrinter As New System.IntPtr()
        Dim objPrintDocument As New Printing.PrintDocument
        Dim BytesNeeded As Integer
        'Dim hPrinterInfo As IntPtr
        Dim pBuf As IntPtr
        Dim pi2 As PRINTER_INFO_2
        Dim pDev As New DEVMODE
        Dim pd As PRINTER_DEFAULTS = Nothing
        Dim nRet As Integer
        Dim ptrDM As IntPtr
        Try
            pd.DesiredAccess = PRINTER_ALL_ACCESS
            sPrnName = objPrintDocument.DefaultPageSettings.PrinterSettings.PrinterName
            If OpenPrinter(sPrnName, hPrinter, pd) Then
                Call GetPrinter(hPrinter, 2, 0, 0, BytesNeeded)

                If Err.LastDllError <> ERROR_INSUFFICIENT_BUFFER Then
                    ClosePrinter(hPrinter)
                    Exit Sub
                End If


                'ReDim bPrinterInfo2(BytesNeeded)
                'pBuf = Runtime.InteropServices.Marshal.AllocHGlobal(BytesNeeded)
                pBuf = Marshal.AllocCoTaskMem(BytesNeeded)
                If GetPrinter(hPrinter, 2, pBuf, BytesNeeded, BytesNeeded) = 0 Then
                    ClosePrinter(hPrinter)
                    Exit Sub
                End If
                'hPrinterInfo = Runtime.InteropServices.Marshal.AllocHGlobal(BytesNeeded)
                'Call GetPrinter(hPrinter, 2, Buffer(0), BytesNeeded, BytesUsed)
                'Runtime.InteropServices.Marshal.Copy(AddofLongValue, ByteArray, 0, 4)
                pi2 = CType(Marshal.PtrToStructure(pBuf, GetType(PRINTER_INFO_2)), PRINTER_INFO_2)

                If (pi2.pDevMode = IntPtr.Zero) Then
                    ' If GetPrinter didn't fill in the DEVMODE, try to get it by calling
                    ' DocumentProperties...
                    'get the size of the devmode structure
                    nRet = CType(DocumentProperties(IntPtr.Zero, hPrinter, sPrnName, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero), Integer)
                    If (nRet <= 0) Then
                        Exit Sub
                    End If
                    ptrDM = Marshal.AllocCoTaskMem(nRet)
                    nRet = CType(DocumentProperties(IntPtr.Zero, hPrinter, sPrnName, ptrDM, IntPtr.Zero, CType(DM_OUT_BUFFER, IntPtr)), Integer)
                    If ((nRet < 0) OrElse (ptrDM = IntPtr.Zero)) Then
                        'Cannot get the DEVMODE structure.
                        Exit Sub
                    End If
                    pi2.pDevMode = ptrDM
                End If

                pDev = CType(Marshal.PtrToStructure(pi2.pDevMode, GetType(DEVMODE)), DEVMODE)
                pDev.dmOrientation = PrinterOrientationConstants.OrientLandscape
                Marshal.StructureToPtr(pDev, pi2.pDevMode, True)
                'nRet = CType(DocumentProperties(IntPtr.Zero, hPrinter, sPrnName, pi2.pDevMode, pi2.pDevMode, CType((DM_IN_BUFFER Or DM_OUT_BUFFER), IntPtr)), Integer)
                'nRet = CType(DocumentProperties(0, hPrinter, sPrnName, pi2.pDevMode, 0, DM_OUT_BUFFER), Integer)
                'If (nRet < 0) Then
                '    'Unable to set duplex setting to this printer.
                '    Exit Sub
                'End If
                Marshal.StructureToPtr(pi2, pBuf, True)
                'Marshal.StructureToPtr(pi2, pi2.pDevMode, True)
                'Call SetPrinter(hPrinter, 2, pBuf, 0)

                If Not SetPrinter(hPrinter, 2, pBuf, 0) Then
                    ClosePrinter(hPrinter)
                    Throw New System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error())
                End If
                ClosePrinter(hPrinter)
                Marshal.FreeHGlobal(pBuf)
                MessageBox.Show("HI")
            End If
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
 
Last edited:
I should introduce you to the [code]Your Code Here[/code] tags, it'll make your code so much easier to read.
 
Back
Top