2010-05-11 101 views
2

這是一樣的this問題,有一個備註: 我們設法拿到printerSettings修改,但如何才能保存回爲默認打印機設置? (原來的問題沒有發佈/回答這個問題)調出打印機設置對話框,並更改保存

的代碼我現在使用:

<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 

爲什麼所做的更改不會保存回任何想法?

回答

2

得到它的工作我有基於代碼更改代碼中發現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")