【问题标题】:Bring up the printer settings dialog and have the changes saved调出打印机设置对话框并保存更改
【发布时间】:2011-02-18 02:40:56
【问题描述】:

这和this的问题一样,只有一句话: 我们设法修改了打印机设置,但我们如何才能将它们保存为默认打印机设置? (原始问题没有发布/回答这个问题)

我现在使用的代码:

<DllImport("winspool.Drv", EntryPoint:="DocumentPropertiesW", SetLastError:=True, _
    ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
  Shared Function DocumentProperties(ByVal hwnd As IntPtr, ByVal hPrinter As IntPtr, _
      <MarshalAs(UnmanagedType.LPWStr)> ByVal pDeviceName As String, _
      ByVal pDevModeOutput As IntPtr, ByVal pDevModeInput As IntPtr, ByVal fMode As Integer) As Integer

   End Function

   <DllImport("kernel32.dll")> _
   Shared Function GlobalLock(ByVal hMem As IntPtr) As IntPtr

   End Function

   <DllImport("kernel32.dll")> _
   Shared Function GlobalUnlock(ByVal hMem As IntPtr) As Boolean

   End Function
   <DllImport("kernel32.dll")> _
   Shared Function GlobalFree(ByVal hMem As IntPtr) As Boolean

   End Function

   <DllImport("winspool.drv")> _
   Shared Function OpenPrinter(ByVal pPrinterName As String, ByRef hPrinter As IntPtr, ByVal pDefault As IntPtr) As Integer

   End Function

   <DllImport("winspool.drv")> _
   Private Shared Function ClosePrinter(ByVal phPrinter As IntPtr) As Integer

   End Function

(对于DocumentProperties,我也尝试将pDevModeInput 设为ByRef 参数)

在 OpenPrinterPropertiesDialog 里面我试过了:

变体 1:

Public Sub OpenPrinterPropertiesDialog(ByVal iPrinterSettings As PrinterSettings)
      Dim hDevMode As IntPtr = iPrinterSettings.GetHdevmode()
      Dim pDevMode As IntPtr = GlobalLock(hDevMode)
      Dim sizeNeeded As Integer = DocumentProperties(mHandle, IntPtr.Zero, iPrinterSettings.PrinterName, pDevMode, pDevMode, 0)
      Dim devModeData As IntPtr = Marshal.AllocHGlobal(sizeNeeded)
      Dim fMode As Integer = 14
      Dim returnCode As Integer = DocumentProperties(mHandle, IntPtr.Zero, iPrinterSettings.PrinterName, devModeData, pDevMode, fMode)

      GlobalUnlock(hDevMode)
      iPrinterSettings.SetHdevmode(devModeData)
      iPrinterSettings.DefaultPageSettings.SetHdevmode(devModeData)

      GlobalFree(hDevMode)
      Marshal.FreeHGlobal(devModeData)
   End Sub

变体 2:

Public Sub OpenPrinterPropertiesDialog(ByVal iPrinterSettings As PrinterSettings)
      Dim printerName As String = iPrinterSettings.PrinterName
      Dim handle As IntPtr
      OpenPrinter(printerName, handle, IntPtr.Zero)

      Dim hDevMode As IntPtr = iPrinterSettings.GetHdevmode(iPrinterSettings.DefaultPageSettings)
      Dim pDevMode As IntPtr = GlobalLock(hDevMode)
      Dim sizeNeeded As Integer = DocumentProperties(mHandle, IntPtr.Zero, iPrinterSettings.PrinterName, pDevMode, pDevMode, 0)
      Dim devModeData As IntPtr = Marshal.AllocHGlobal(sizeNeeded)
      Dim fMode As Integer = 14
      Dim returnCode As Integer = DocumentProperties(mHandle, IntPtr.Zero, iPrinterSettings.PrinterName, devModeData, pDevMode, fMode)

      GlobalUnlock(hDevMode)
      iPrinterSettings.SetHdevmode(devModeData)
      iPrinterSettings.DefaultPageSettings.SetHdevmode(devModeData)
      returnCode = DocumentProperties(IntPtr.Zero, IntPtr.Zero, iPrinterSettings.PrinterName, devModeData, pDevMode, 2)

      ClosePrinter(handle)
      GlobalFree(hDevMode)
      Marshal.FreeHGlobal(devModeData)
   End Sub

关于为什么没有保存更改的任何想法?

【问题讨论】:

    标签: .net vb.net winapi printing pinvoke


    【解决方案1】:

    为了让它工作,我必须根据找到的代码更改代码 here(感谢 umeshb 分享它!)

    我现在使用的代码(在 XP 上工作)是:(请随意优化)

    Public Class PrinterSettingsHelper
    #Region "Private Variables"
       Private gPrinter As IntPtr = New System.IntPtr()
       Private gPrinterValues As PRINTER_DEFAULTS = New PRINTER_DEFAULTS()
       Private gPInfo As PRINTER_INFO_2 = New PRINTER_INFO_2()
       Private gDevMode As DEVMODE
       Private gPtrDevMode As IntPtr
       Private gPtrPrinterInfo As IntPtr
       Private gSizeOfDevMode As Integer = 0
       Private gLastError As Integer
       Private gNBytesNeeded As Integer
       Private gNRet As Long
       Private gIntError As Integer
       Private gNTemporary As Int32
       Private gDevModeData As IntPtr
    #End Region
    #Region "Data structure"
       <StructLayout(LayoutKind.Sequential)> _
       Public Structure PRINTER_DEFAULTS
          Public pDatatype As Integer
          Public pDevMode As Integer
          Public DesiredAccess As Integer
       End Structure
    
       <StructLayout(LayoutKind.Sequential)> _
       Private Structure PRINTER_INFO_2
          <MarshalAs(UnmanagedType.LPStr)> Public pServerName As String
          <MarshalAs(UnmanagedType.LPStr)> Public pPrinterName As String
          <MarshalAs(UnmanagedType.LPStr)> Public pShareName As String
          <MarshalAs(UnmanagedType.LPStr)> Public pPortName As String
          <MarshalAs(UnmanagedType.LPStr)> Public pDriverName As String
          <MarshalAs(UnmanagedType.LPStr)> Public pComment As String
          <MarshalAs(UnmanagedType.LPStr)> Public pLocation As String
          Public pDevMode As IntPtr
          <MarshalAs(UnmanagedType.LPStr)> Public pSepFile As String
          <MarshalAs(UnmanagedType.LPStr)> Public pPrintProcessor As String
          <MarshalAs(UnmanagedType.LPStr)> Public pDatatype As String
          <MarshalAs(UnmanagedType.LPStr)> Public pParameters As String
          Public pSecurityDescriptor As IntPtr
          Public Attributes As Int32
          Public Priority As Int32
          Public DefaultPriority As Int32
          Public StartTime As Int32
          Public UntilTime As Int32
          Public Status As Int32
          Public cJobs As Int32
          Public AveragePPM As Int32
       End Structure
    
       Private Const CCDEVICENAME As Short = 32
       Private Const CCFORMNAME As Short = 32
    
       <StructLayout(LayoutKind.Sequential)> _
       Public Structure DEVMODE
          <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=CCDEVICENAME)> _
          Public dmDeviceName As String
          Public dmSpecVersion As Short
          Public dmDriverVersion As Short
          Public dmSize As Short
          Public dmDriverExtra As Short
          Public dmFields As Integer
          Public dmOrientation As Short
          Public dmPaperSize As Short
          Public dmPaperLength As Short
          Public dmPaperWidth As Short
          Public dmScale As Short
          Public dmCopies As Short
          Public dmDefaultSource As Short
          Public dmPrintQuality As Short
          Public dmColor As Short
          Public dmDuplex As Short
          Public dmYResolution As Short
          Public dmTTOption As Short
          Public dmCollate As Short
          <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=CCFORMNAME)> _
          Public dmFormName As String
          Public dmUnusedPadding As Short
          Public dmBitsPerPel As Short
          Public dmPelsWidth As Integer
          Public dmPelsHeight As Integer
          Public dmDisplayFlags As Integer
          Public dmDisplayFrequency As Integer
       End Structure
    
    #End Region
    #Region "Win API Def"
       <DllImport("kernel32.dll", EntryPoint:="GetLastError", SetLastError:=False, _
       ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
       Private Shared Function GetLastError() As Int32
    
       End Function
    
       <DllImport("winspool.Drv", EntryPoint:="ClosePrinter", SetLastError:=True, _
       ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
       Private Shared Function ClosePrinter(ByVal hPrinter As IntPtr) As Boolean
    
       End Function
    
       <DllImport("winspool.Drv", EntryPoint:="DocumentPropertiesA", SetLastError:=True, _
       ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
       Private Shared Function DocumentProperties(ByVal hwnd As IntPtr, ByVal hPrinter As IntPtr, _
        <MarshalAs(UnmanagedType.LPStr)> ByVal pDeviceNameg As String, _
       ByVal pDevModeOutput As IntPtr, ByRef pDevModeInput As IntPtr, ByVal fMode As Integer) As Integer
    
       End Function
    
       <DllImport("winspool.Drv", EntryPoint:="GetPrinterA", SetLastError:=True, _
           CharSet:=CharSet.Ansi, ExactSpelling:=True, _
           CallingConvention:=CallingConvention.StdCall)> _
       Private Shared Function GetPrinter(ByVal hPrinter As IntPtr, ByVal dwLevel As Int32, _
       ByVal pPrinter As IntPtr, ByVal dwBuf As Int32, ByRef dwNeeded As Int32) As Boolean
       End Function
    
       <DllImport("winspool.Drv", EntryPoint:="OpenPrinterA", _
           SetLastError:=True, CharSet:=CharSet.Ansi, _
           ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
       Private Shared Function OpenPrinter(<MarshalAs(UnmanagedType.LPStr)> ByVal szPrinter As String, _
           ByRef hPrinter As IntPtr, ByRef pd As PRINTER_DEFAULTS) As Boolean
    
       End Function
    
       <DllImport("winspool.drv", CharSet:=CharSet.Ansi, SetLastError:=True)> _
       Private Shared Function SetPrinter(ByVal hPrinter As IntPtr, ByVal Level As Integer, _
                                          ByVal pPrinter As IntPtr, ByVal Command As Integer) As Boolean
    
       End Function
    #End Region
    
    #Region "Constants"
       Private Const DM_DUPLEX As Integer = 4096 '0x1000
       Private Const DM_IN_BUFFER As Integer = 8
       Private Const DM_OUT_BUFFER As Integer = 2
       Private Const PRINTER_ACCESS_ADMINISTER As Integer = 4 '0x4
       Private Const STANDARD_RIGHTS_REQUIRED As Integer = 983040 '0xF0000
       Private Const PRINTER_ALL_ACCESS As Integer = STANDARD_RIGHTS_REQUIRED Or PRINTER_ACCESS_ADMINISTER Or PRINTER_ACCESS_USE
       Private Const PRINTER_ACCESS_USE As Integer = 8 '0x8
    #End Region
    
    #Region "Function to change printer settings"
       Public Function ChangePrinterSetting(ByVal iPrinterName As String) As Boolean
          gDevMode = Me.GetPrinterSettings(iPrinterName)
          Marshal.StructureToPtr(gDevMode, gDevModeData, True)
          gPInfo.pDevMode = gDevModeData
          gPInfo.pSecurityDescriptor = IntPtr.Zero
          'bring up the printer preferences dialog
          DocumentProperties(IntPtr.Zero, gPrinter, iPrinterName, gDevModeData _
              , gPInfo.pDevMode, DM_IN_BUFFER Or DM_OUT_BUFFER Or PRINTER_ACCESS_ADMINISTER)
          'update driver dependent part of the DEVMODE 
          Marshal.StructureToPtr(gPInfo, gPtrPrinterInfo, True)
          gLastError = Marshal.GetLastWin32Error()
          gNRet = Convert.ToInt16(SetPrinter(gPrinter, 2, gPtrPrinterInfo, 0))
          If gNRet = 0 Then
             'Unable to set shared printer settings.
             gLastError = Marshal.GetLastWin32Error()
             Throw New Exception(Marshal.GetLastWin32Error().ToString)
          End If
          If gPrinter <> IntPtr.Zero Then
             ClosePrinter(gPrinter)
          End If
          Return Convert.ToBoolean(gNRet)
       End Function
    
       Private Function GetPrinterSettings(ByVal PrinterName As String) As DEVMODE
          Dim lDevMode As DEVMODE
          gPrinterValues.pDatatype = 0
          gPrinterValues.pDevMode = 0
          gPrinterValues.DesiredAccess = PRINTER_ALL_ACCESS
          gNRet = Convert.ToInt32(OpenPrinter(PrinterName, _
                         gPrinter, gPrinterValues))
          If gNRet = 0 Then
             gLastError = Marshal.GetLastWin32Error()
             Throw New Exception(Marshal.GetLastWin32Error().ToString())
          End If
    
          GetPrinter(gPrinter, 2, IntPtr.Zero, 0, gNBytesNeeded)
          If gNBytesNeeded <= 0 Then
             Throw New System.Exception("Unable to allocate memory")
          Else
             ' Allocate enough space for PRINTER_INFO_2... 
             gPtrPrinterInfo = Marshal.AllocCoTaskMem(gNBytesNeeded)
             gPtrPrinterInfo = Marshal.AllocHGlobal(gNBytesNeeded)
             'The second GetPrinter fills in all the current settings, so all you 
             'need to do is modify what you're interested in...
             gNRet = Convert.ToInt32(GetPrinter(gPrinter, 2, _
                 gPtrPrinterInfo, gNBytesNeeded, gNTemporary))
             If gNRet = 0 Then
                gLastError = Marshal.GetLastWin32Error()
                Throw New Exception(Marshal.GetLastWin32Error().ToString())
             End If
             gPInfo = CType(Marshal.PtrToStructure(gPtrPrinterInfo, GetType(PRINTER_INFO_2)), PRINTER_INFO_2)
             Dim lTempBuffer As IntPtr = New IntPtr()
             If gPInfo.pDevMode = IntPtr.Zero Then
                'If GetPrinter didn't fill in the DEVMODE, try to get it by calling
                'DocumentProperties...
                Dim ptrZero As IntPtr = IntPtr.Zero
                'get the size of the devmode structure
                gSizeOfDevMode = DocumentProperties(IntPtr.Zero, gPrinter, _
                                   PrinterName, ptrZero, ptrZero, 0)
                gPtrDevMode = Marshal.AllocCoTaskMem(gSizeOfDevMode)
                Dim i As Integer = DocumentProperties(IntPtr.Zero, gPrinter, PrinterName, gPtrDevMode, _
                ptrZero, DM_OUT_BUFFER)
                If (i < 0) OrElse (gPtrDevMode <> IntPtr.Zero) Then
                   'Cannot get the DEVMODE structure.
                   Throw New System.Exception("Cannot get DEVMODE data")
                End If
                gPInfo.pDevMode = gPtrDevMode
             End If
             gIntError = DocumentProperties(IntPtr.Zero, gPrinter, _
                       PrinterName, IntPtr.Zero, lTempBuffer, 0)
             gDevModeData = Marshal.AllocHGlobal(gIntError)
             gIntError = DocumentProperties(IntPtr.Zero, gPrinter, _
                      PrinterName, gDevModeData, lTempBuffer, 2)
             lDevMode = CType(Marshal.PtrToStructure(gDevModeData, GetType(DEVMODE)), DEVMODE)
             If (gNRet = 0) OrElse (gPrinter = IntPtr.Zero) Then
                gLastError = Marshal.GetLastWin32Error()
                Throw New Exception(Marshal.GetLastWin32Error().ToString())
             End If
             Return lDevMode
          End If
       End Function
    #End Region
    End Class
    

    并使用这个类:

     Dim lPrinterpreferences As PrinterSettingsHelper = New PrinterSettingsHelper()
             lPrinterpreferences.ChangePrinterSetting("MyFavouritePrinter")
    

    【讨论】:

      猜你喜欢
      • 2012-01-28
      • 1970-01-01
      • 1970-01-01
      • 2011-01-27
      • 1970-01-01
      • 2010-10-18
      • 2013-06-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多