Click here to Skip to main content
15,888,148 members
Articles / Desktop Programming / MFC

Changing printer settings using C#

Rate me:
Please Sign up or sign in to vote.
2.65/5 (35 votes)
29 Apr 2004CPOL1 min read 458K   71   66
Changing printer settings using C#.

Introduction

I was working on one of the migration projects from VB6 to C#. I had a requirement of printing MS Word document for the application, and the user should be given an option to change printer settings for the document that he/she wants to print, so that user can change page source and duplex property of the printer.

When we started converting code to C#, I found that there is no function in MS Word API to change the duplex property of the printer. Word does provide a parameter in WordApplication class’ PrintOut method, but Microsoft suggests not to use as it is OS and language dependent.

What really worrying was the printing library in .NET. I did not find any class which could change the printer setting with out PrintDocument associated with it. I really feel that .NET should have provided class to change printer settings, or for that matter, .NET should have provided a library which helps prevent developers end up using WIN API which is OS dependent (I ended up in designing a class for printer which is OS independent).

The other problem is, the OpenPrinter does not work for network printers (although Microsoft suggests a way of setting up the printer, I can’t do the same with the client). The funny part is that the VB6 code works without any problem (access denied) and all MS Office tools work all right, then why not C# code?

Following is the C# code to change printer settings globally. This is only a sample code. Please excuse me as the code is not elegantly written, the only intention was to explain how it works. The code will not work for network printers. Please refer the following link for more information for setting up network printer.

C#
public class PrinterSettings 
{
#region "Private Variables"
private IntPtr hPrinter = new System.IntPtr() ;
private PRINTER_DEFAULTS PrinterValues = new PRINTER_DEFAULTS();
private PRINTER_INFO_2 pinfo = new PRINTER_INFO_2();
private DEVMODE dm;
private IntPtr ptrDM;
private IntPtr ptrPrinterInfo;
private int sizeOfDevMode = 0;
private int lastError;
private int nBytesNeeded;
private long nRet; 
private int intError;
private System.Int32 nJunk;
private IntPtr yDevModeData;

#endregion
#region "Win API Def"
[DllImport("kernel32.dll", EntryPoint="GetLastError", SetLastError=false,
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
private static extern Int32 GetLastError();
[DllImport("winspool.Drv", EntryPoint="ClosePrinter", SetLastError=true, 
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
private static extern bool ClosePrinter(IntPtr hPrinter);
[DllImport("winspool.Drv", EntryPoint="DocumentPropertiesA", SetLastError=true, 
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
private static extern int DocumentProperties (IntPtr hwnd, IntPtr hPrinter, 
[MarshalAs(UnmanagedType.LPStr)] string pDeviceNameg, 
IntPtr pDevModeOutput, ref IntPtr pDevModeInput, int fMode);
[DllImport("winspool.Drv", EntryPoint="GetPrinterA", SetLastError=true, 
    CharSet=CharSet.Ansi, ExactSpelling=true, 
    CallingConvention=CallingConvention.StdCall)]
private static extern bool GetPrinter(IntPtr hPrinter, Int32 dwLevel, 
IntPtr pPrinter, Int32 dwBuf, out Int32 dwNeeded);
/*[DllImport("winspool.Drv", EntryPoint="OpenPrinterA", 
    SetLastError=true, CharSet=CharSet.Ansi, 
    ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, 
out IntPtr hPrinter, ref PRINTER_DEFAULTS pd)

[ DllImport( "winspool.drv",CharSet=CharSet.Unicode,ExactSpelling=false,
CallingConvention=CallingConvention.StdCall )]
public static extern long OpenPrinter(string pPrinterName, 
         ref IntPtr phPrinter, int pDefault);*/

/*[DllImport("winspool.Drv", EntryPoint="OpenPrinterA", 
    SetLastError=true, CharSet=CharSet.Ansi, 
    ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, 
out IntPtr hPrinter, ref PRINTER_DEFAULTS pd);
*/ 
[DllImport("winspool.Drv", EntryPoint="OpenPrinterA", 
    SetLastError=true, CharSet=CharSet.Ansi, 
    ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
private static extern bool 
    OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, 
    out IntPtr hPrinter, ref PRINTER_DEFAULTS pd);
[DllImport("winspool.drv", CharSet=CharSet.Ansi, SetLastError=true)]
private static extern bool SetPrinter(IntPtr hPrinter, int Level, IntPtr 
pPrinter, int Command);

/*[DllImport("winspool.drv", CharSet=CharSet.Ansi, SetLastError=true)]
private static extern bool SetPrinter(IntPtr hPrinter, int Level, IntPtr 
pPrinter, int Command);*/

// Wrapper for Win32 message formatter.
/*[DllImport("kernel32.dll", CharSet=System.Runtime.InteropServices.CharSet.Auto)]
private unsafe static extern int FormatMessage( int dwFlags,
ref IntPtr pMessageSource,
int dwMessageID,
int dwLanguageID,
ref string lpBuffer,
int nSize,
IntPtr* pArguments);*/
#endregion
#region "Data structure"
[StructLayout(LayoutKind.Sequential)]
public struct PRINTER_DEFAULTS
{
public int pDatatype;
public int pDevMode;
public int DesiredAccess;
}
/*[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
public struct PRINTER_DEFAULTS
{
public int pDataType;
public IntPtr pDevMode;
public ACCESS_MASK DesiredAccess;
}*/

[StructLayout(LayoutKind.Sequential)]
private struct PRINTER_INFO_2
{
[MarshalAs(UnmanagedType.LPStr)] public string pServerName; 
[MarshalAs(UnmanagedType.LPStr)] public string pPrinterName; 
[MarshalAs(UnmanagedType.LPStr)] public string pShareName; 
[MarshalAs(UnmanagedType.LPStr)] public string pPortName; 
[MarshalAs(UnmanagedType.LPStr)] public string pDriverName; 
[MarshalAs(UnmanagedType.LPStr)] public string pComment; 
[MarshalAs(UnmanagedType.LPStr)] public string pLocation; 
public IntPtr pDevMode; 
[MarshalAs(UnmanagedType.LPStr)] public string pSepFile; 
[MarshalAs(UnmanagedType.LPStr)] public string pPrintProcessor; 
[MarshalAs(UnmanagedType.LPStr)] public string pDatatype; 
[MarshalAs(UnmanagedType.LPStr)] public string pParameters; 
public IntPtr pSecurityDescriptor; 
public Int32 Attributes; 
public Int32 Priority; 
public Int32 DefaultPriority; 
public Int32 StartTime; 
public Int32 UntilTime; 
public Int32 Status; 
public Int32 cJobs; 
public Int32 AveragePPM; 
}
private const short CCDEVICENAME = 32;
private const short CCFORMNAME = 32;
[StructLayout(LayoutKind.Sequential)] 
public struct DEVMODE 
{ 
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCDEVICENAME)] 
public string dmDeviceName;
public short dmSpecVersion;
public short dmDriverVersion;
public short dmSize;
public short dmDriverExtra;
public int dmFields;
public short dmOrientation;
public short dmPaperSize;
public short dmPaperLength;
public short dmPaperWidth;
public short dmScale;
public short dmCopies;
public short dmDefaultSource;
public short dmPrintQuality;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCFORMNAME)] 
public string dmFormName; 
public short dmUnusedPadding;
public short dmBitsPerPel;
public int dmPelsWidth;
public int dmPelsHeight;
public int dmDisplayFlags;
public int dmDisplayFrequency;
}
#endregion
#region "Constants"
private const int DM_DUPLEX = 0x1000;
private const int DM_IN_BUFFER = 8;
private const int DM_OUT_BUFFER = 2;
private const int PRINTER_ACCESS_ADMINISTER = 0x4;
private const int PRINTER_ACCESS_USE = 0x8;
private const int STANDARD_RIGHTS_REQUIRED = 0xF0000;
private const int PRINTER_ALL_ACCESS = 
    (STANDARD_RIGHTS_REQUIRED | PRINTER_ACCESS_ADMINISTER 
    | PRINTER_ACCESS_USE);
#endregion
#region "Function to change printer settings" 
public bool ChangePrinterSetting(string PrinterName,PrinterData PS)

{

if (((int)PS.Duplex < 1) || ((int)PS.Duplex > 3) )
{
throw new ArgumentOutOfRangeException("nDuplexSetting",
                         "nDuplexSetting is incorrect.");
}
else
{
dm = this.GetPrinterSettings( PrinterName);
dm.dmDefaultSource =(short)PS.source; 
dm.dmOrientation = (short)PS.Orientation; 
dm.dmPaperSize =(short)PS.Size;
dm.dmDuplex = (short)PS.Duplex; 
Marshal.StructureToPtr( dm,yDevModeData,true); 
pinfo.pDevMode = yDevModeData;
pinfo.pSecurityDescriptor = IntPtr.Zero;
/*update driver dependent part of the DEVMODE
1 = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, yDevModeData
, ref pinfo.pDevMode, (DM_IN_BUFFER | DM_OUT_BUFFER));*/
Marshal.StructureToPtr(pinfo,ptrPrinterInfo,true); 
lastError = Marshal.GetLastWin32Error();
nRet = Convert.ToInt16(SetPrinter(hPrinter, 2, ptrPrinterInfo, 0));
if (nRet == 0)
{
//Unable to set shared printer settings.
lastError = Marshal.GetLastWin32Error();
//string myErrMsg = GetErrorMessage(lastError);
throw new Win32Exception(Marshal.GetLastWin32Error()); 

}
if (hPrinter != IntPtr.Zero) 
ClosePrinter(hPrinter);
return Convert.ToBoolean(nRet);
}
}
private DEVMODE GetPrinterSettings(string PrinterName)
{
PrinterData PData = new PrinterData(); 
DEVMODE dm;
const int PRINTER_ACCESS_ADMINISTER = 0x4;
const int PRINTER_ACCESS_USE = 0x8;
const int PRINTER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | 
           PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE);


PrinterValues.pDatatype =0;
PrinterValues.pDevMode = 0 ;
PrinterValues.DesiredAccess = PRINTER_ALL_ACCESS;
nRet = Convert.ToInt32(OpenPrinter(PrinterName, 
               out hPrinter, ref PrinterValues));
if (nRet == 0)
{
lastError = Marshal.GetLastWin32Error();
throw new Win32Exception(Marshal.GetLastWin32Error()); 
}
GetPrinter(hPrinter, 2, IntPtr.Zero, 0, out nBytesNeeded);
if (nBytesNeeded <= 0)
{
throw new System.Exception("Unable to allocate memory");
}
else
{
// Allocate enough space for PRINTER_INFO_2... 
{ptrPrinterIn fo = Marshal.AllocCoTaskMem(nBytesNeeded)};
ptrPrinterInfo = Marshal.AllocHGlobal(nBytesNeeded);
// The second GetPrinter fills in all the current settings, so all you 
// need to do is modify what you're interested in...
nRet = Convert.ToInt32(GetPrinter(hPrinter, 2, 
    ptrPrinterInfo, nBytesNeeded, out nJunk));
if (nRet == 0)
{
lastError = Marshal.GetLastWin32Error();
throw new Win32Exception(Marshal.GetLastWin32Error()); 
}
pinfo = (PRINTER_INFO_2)Marshal.PtrToStructure(ptrPrinterInfo, 
                                      typeof(PRINTER_INFO_2));
IntPtr Temp = new IntPtr();
if (pinfo.pDevMode == IntPtr.Zero)
{
// If GetPrinter didn't fill in the DEVMODE, try to get it by calling
// DocumentProperties...
IntPtr ptrZero = IntPtr.Zero;
//get the size of the devmode structure
sizeOfDevMode = DocumentProperties(IntPtr.Zero, hPrinter, 
                   PrinterName, ptrZero, ref ptrZero, 0);

ptrDM = Marshal.AllocCoTaskMem(sizeOfDevMode);
int i ;
i = DocumentProperties(IntPtr.Zero, hPrinter, PrinterName, ptrDM, 
ref ptrZero, DM_OUT_BUFFER);
if ((i < 0) || (ptrDM == IntPtr.Zero))
{
//Cannot get the DEVMODE structure.
throw new System.Exception("Cannot get DEVMODE data"); 
}
pinfo.pDevMode = ptrDM;
}
intError = DocumentProperties(IntPtr.Zero, hPrinter, 
          PrinterName, IntPtr.Zero , ref Temp , 0);
//IntPtr yDevModeData = Marshal.AllocCoTaskMem(i1);
yDevModeData= Marshal.AllocHGlobal(intError);
intError = DocumentProperties(IntPtr.Zero, hPrinter, 
         PrinterName, yDevModeData , ref Temp , 2);
dm = (DEVMODE)Marshal.PtrToStructure(yDevModeData, typeof(DEVMODE));
//nRet = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, yDevModeData
// , ref yDevModeData, (DM_IN_BUFFER | DM_OUT_BUFFER));
if ((nRet == 0) || (hPrinter == IntPtr.Zero))
{
lastError = Marshal.GetLastWin32Error();
//string myErrMsg = GetErrorMessage(lastError);
throw new Win32Exception(Marshal.GetLastWin32Error()); 
}
return dm;
}
#endregion
}}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
France France
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionSuddenly Not Working Pin
Gs5a6216-Jan-24 8:57
Gs5a6216-Jan-24 8:57 
Suggestion64bit Chagne Pin
tonyzhangemtek15-Feb-23 12:55
tonyzhangemtek15-Feb-23 12:55 
QuestionChange advanced property - print spooled document first Pin
shoshana.tzi24-Dec-18 19:24
shoshana.tzi24-Dec-18 19:24 
Question64 bits incompatibility Pin
jdsama64-Jul-17 5:01
professionaljdsama64-Jul-17 5:01 
QuestionChanging the printer settings - doesn't work Pin
naveenchand18-Sep-16 23:43
naveenchand18-Sep-16 23:43 
QuestionWorked but with small modifications Pin
blastnsmash12-Oct-15 14:55
blastnsmash12-Oct-15 14:55 
QuestionWindows 7 Pin
GeekInOnLife26-Sep-13 6:04
professionalGeekInOnLife26-Sep-13 6:04 
AnswerRe: Windows 7 Pin
oware7-Oct-13 4:34
oware7-Oct-13 4:34 
GeneralMy vote of 1 Pin
MirJoya3-Sep-13 22:32
MirJoya3-Sep-13 22:32 
GeneralRe: My vote of 1 Pin
oware4-Oct-13 12:01
oware4-Oct-13 12:01 
QuestionPrevent Collation when printing multiple copies Pin
Member 810781110-May-13 5:26
Member 810781110-May-13 5:26 
QuestionSample for orientage win2008r2 Pin
Member 87974608-Apr-12 2:29
Member 87974608-Apr-12 2:29 
General'Access denied'-problem Pin
Daniel_Komrakov12-Mar-12 0:35
Daniel_Komrakov12-Mar-12 0:35 
QuestionChange Advance printer settings need help Pin
santy_dabs20-Dec-11 13:54
santy_dabs20-Dec-11 13:54 
QuestionCommunication with Printer Driver in Delphi Pin
ariswidiantoro26-Oct-11 17:17
ariswidiantoro26-Oct-11 17:17 
QuestionSolution: Access network printers Pin
lakai_4-Aug-11 4:13
lakai_4-Aug-11 4:13 
AnswerRe: Solution: Access network printers Pin
kunalkalra6-Sep-12 19:18
kunalkalra6-Sep-12 19:18 
Questionprinter settings control Pin
Zil-e-Huma2-Aug-11 19:18
Zil-e-Huma2-Aug-11 19:18 
Questiongetting started with printer settings Pin
Zil-e-Huma1-Aug-11 22:25
Zil-e-Huma1-Aug-11 22:25 
QuestionHow to enable setPrinter to work on networkprinters.... Pin
Henry12345674-Feb-11 0:55
Henry12345674-Feb-11 0:55 
GeneralChangePrinterSettings Pin
GuruCoder4-Jan-10 5:07
GuruCoder4-Jan-10 5:07 
GeneralDuplex Pin
GuruCoder30-Dec-09 9:35
GuruCoder30-Dec-09 9:35 
GeneralGreat work !! Pin
Nomkin11-Nov-09 2:24
Nomkin11-Nov-09 2:24 
GeneralVB.NET port of the above code Pin
Armoghan Asif3-Nov-09 2:43
Armoghan Asif3-Nov-09 2:43 
Imports System
Imports System.Runtime.InteropServices
Imports System.ComponentModel
Public Class PrinterData
      Public Duplex As Short
      Public source As Short
      Public Orientation As Short
      Public Size As Short
End Class
Public Class PrinterSettings
#Region "Private Variables"
      Private hPrinter As IntPtr = New System.IntPtr()
      Private PrinterValues As New PRINTER_DEFAULTS()
      Private pinfo As New PRINTER_INFO_2()
      Private dm As DEVMODE
      Private ptrDM As IntPtr
      Private ptrPrinterInfo As IntPtr
      Private sizeOfDevMode As Integer = 0
      Private lastError As Integer
      Private nBytesNeeded As Integer
      Private nRet As Long
      Private intError As Integer
      Private nJunk As Integer
      Private yDevModeData As IntPtr
#End Region
#Region "Win API Def"
      &lt;DllImport("kernel32.dll", EntryPoint:="GetLastError", SetLastError:=False, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)&gt; _
      Private Shared Function GetLastError() As Int32
      End Function
      &lt;DllImport("winspool.Drv", EntryPoint:="ClosePrinter", SetLastError:=True, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)&gt; _
      Private Shared Function ClosePrinter(ByVal hPrinter As IntPtr) As Boolean
      End Function
      &lt;DllImport("winspool.Drv", EntryPoint:="DocumentPropertiesA", SetLastError:=True, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)&gt; _
      Private Shared Function DocumentProperties(ByVal hwnd As IntPtr, ByVal hPrinter As IntPtr, &lt;MarshalAs(UnmanagedType.LPStr)&gt; _
   ByVal pDeviceNameg As String, ByVal pDevModeOutput As IntPtr, ByRef pDevModeInput As IntPtr, ByVal fMode As Integer) As Integer
      End Function
      &lt;DllImport("winspool.Drv", EntryPoint:="GetPrinterA", SetLastError:=True, CharSet:=CharSet.Ansi, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)&gt; _
      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)]
      '      static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter,
      '      out IntPtr hPrinter, ref PRINTER_DEFAULTS pd)      '
      '      [ DllImport( "winspool.drv",CharSet=CharSet.Unicode,ExactSpelling=false,
      '      CallingConvention=CallingConvention.StdCall )]
      '      public static extern long OpenPrinter(string pPrinterName,
      '                  ref IntPtr phPrinter, int pDefault);
      '[DllImport("winspool.Drv", EntryPoint="OpenPrinterA",
      '            SetLastError=true, CharSet=CharSet.Ansi,
      '            ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
      '      static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter,
      '      out IntPtr hPrinter, ref PRINTER_DEFAULTS pd);
      '     
      &lt;DllImport("winspool.Drv", EntryPoint:="OpenPrinterA", SetLastError:=True, CharSet:=CharSet.Ansi, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)&gt; _
      Private Shared Function OpenPrinter(&lt;MarshalAs(UnmanagedType.LPStr)&gt; _
   ByVal szPrinter As String, ByRef hPrinter As IntPtr, ByRef pd As PRINTER_DEFAULTS) As Boolean
      End Function
      &lt;DllImport("winspool.drv", CharSet:=CharSet.Ansi, SetLastError:=True)&gt; _
      Private Shared Function SetPrinter(ByVal hPrinter As IntPtr, ByVal Level As Integer, ByVal pPrinter As IntPtr, ByVal Command As Integer) As Boolean
      End Function
      '[DllImport("winspool.drv", CharSet=CharSet.Ansi, SetLastError=true)]
      '      private static extern bool SetPrinter(IntPtr hPrinter, int Level, IntPtr
      '      pPrinter, int Command);
      ' Wrapper for Win32 message formatter.
      '[DllImport("kernel32.dll", CharSet=System.Runtime.InteropServices.CharSet.Auto)]
      '      private unsafe static extern int FormatMessage( int dwFlags,
      '      ref IntPtr pMessageSource,      '      int dwMessageID,
      '      int dwLanguageID,      '      ref string lpBuffer,      '      int nSize,
      '      IntPtr* pArguments);
#End Region
#Region "Data structure"
      &lt;StructLayout(LayoutKind.Sequential)&gt; _
      Public Structure PRINTER_DEFAULTS
            Public pDatatype As Integer
            Public pDevMode As Integer
            Public DesiredAccess As Integer
      End Structure
      '[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
      '      public struct PRINTER_DEFAULTS      '      {      '      public int pDataType;
      '      public IntPtr pDevMode;      '      public ACCESS_MASK DesiredAccess;
      '      }
      &lt;StructLayout(LayoutKind.Sequential)&gt; _
      Private Structure PRINTER_INFO_2
            &lt;MarshalAs(UnmanagedType.LPStr)&gt; _
            Public pServerName As String
            &lt;MarshalAs(UnmanagedType.LPStr)&gt; _
            Public pPrinterName As String
            &lt;MarshalAs(UnmanagedType.LPStr)&gt; _
            Public pShareName As String
            &lt;MarshalAs(UnmanagedType.LPStr)&gt; _
            Public pPortName As String
            &lt;MarshalAs(UnmanagedType.LPStr)&gt; _
            Public pDriverName As String
            &lt;MarshalAs(UnmanagedType.LPStr)&gt; _
            Public pComment As String
            &lt;MarshalAs(UnmanagedType.LPStr)&gt; _
            Public pLocation As String
            Public pDevMode As IntPtr
            &lt;MarshalAs(UnmanagedType.LPStr)&gt; _
            Public pSepFile As String
            &lt;MarshalAs(UnmanagedType.LPStr)&gt; _
            Public pPrintProcessor As String
            &lt;MarshalAs(UnmanagedType.LPStr)&gt; _
            Public pDatatype As String
            &lt;MarshalAs(UnmanagedType.LPStr)&gt; _
            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
      &lt;StructLayout(LayoutKind.Sequential)&gt; _
      Public Structure DEVMODE
            &lt;MarshalAs(UnmanagedType.ByValTStr, SizeConst:=CCDEVICENAME)&gt; _
            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
            &lt;MarshalAs(UnmanagedType.ByValTStr, SizeConst:=CCFORMNAME)&gt; _
            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 "Constants"
      Private Const DM_DUPLEX As Integer = 4096
      Private Const DM_IN_BUFFER As Integer = 8
      Private Const DM_OUT_BUFFER As Integer = 2
      Private Const PRINTER_ACCESS_ADMINISTER As Integer = 4
      Private Const PRINTER_ACCESS_USE As Integer = 8
      Private Const STANDARD_RIGHTS_REQUIRED As Integer = 983040
      Private Const PRINTER_ALL_ACCESS As Integer = (STANDARD_RIGHTS_REQUIRED Or PRINTER_ACCESS_ADMINISTER Or PRINTER_ACCESS_USE)
#End Region
#Region "Function to change printer settings"


      Public Function ChangePrinterSetting(ByVal PrinterName As String, ByVal PS As PrinterData) As Boolean
            If (DirectCast(PS.Duplex, Short) &lt; 1) OrElse (DirectCast(PS.Duplex, Short) &gt; 3) Then
                  Throw New ArgumentOutOfRangeException("nDuplexSetting", "nDuplexSetting is incorrect.")
            Else
                  dm = Me.GetPrinterSettings(PrinterName)
                  dm.dmDefaultSource = DirectCast(PS.source, Short)
                  dm.dmOrientation = DirectCast(PS.Orientation, Short)
                  dm.dmPaperSize = DirectCast(PS.Size, Short)
                  dm.dmDuplex = DirectCast(PS.Duplex, Short)
                  Marshal.StructureToPtr(dm, yDevModeData, True)
                  pinfo.pDevMode = yDevModeData
                  pinfo.pSecurityDescriptor = IntPtr.Zero
                  'update driver dependent part of the DEVMODE
                  '                  1 = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, yDevModeData
                  '                  , ref pinfo.pDevMode, (DM_IN_BUFFER | DM_OUT_BUFFER));
                  Marshal.StructureToPtr(pinfo, ptrPrinterInfo, True)
                  lastError = Marshal.GetLastWin32Error()
                  nRet = Convert.ToInt16(SetPrinter(hPrinter, 2, ptrPrinterInfo, 0))
                  If nRet = 0 Then
                        'Unable to set shared printer settings.
                        lastError = Marshal.GetLastWin32Error()
                        'string myErrMsg = GetErrorMessage(lastError);
                        Throw New Win32Exception(Marshal.GetLastWin32Error())
                  End If
                  If hPrinter &lt;&gt; IntPtr.Zero Then
                        ClosePrinter(hPrinter)
                  End If
                  Return Convert.ToBoolean(nRet)
            End If
      End Function
      Private Function GetPrinterSettings(ByVal PrinterName As String) As DEVMODE
            Dim PData As New PrinterData()
            Dim dm As DEVMODE
            Const PRINTER_ACCESS_ADMINISTER As Integer = 4
            Const PRINTER_ACCESS_USE As Integer = 8
            Const PRINTER_ALL_ACCESS As Integer = (STANDARD_RIGHTS_REQUIRED Or PRINTER_ACCESS_ADMINISTER Or PRINTER_ACCESS_USE)
            PrinterValues.pDatatype = 0
            PrinterValues.pDevMode = 0
            PrinterValues.DesiredAccess = PRINTER_ALL_ACCESS
            nRet = Convert.ToInt32(OpenPrinter(PrinterName, hPrinter, PrinterValues))
            If nRet = 0 Then
                  lastError = Marshal.GetLastWin32Error()
                  Throw New Win32Exception(Marshal.GetLastWin32Error())
            End If
            GetPrinter(hPrinter, 2, IntPtr.Zero, 0, nBytesNeeded)
            If nBytesNeeded &lt;= 0 Then
                  Throw New System.Exception("Unable to allocate memory")
            Else
                  ' Allocate enough space for PRINTER_INFO_2...
                  ptrPrinterInfo = Marshal.AllocCoTaskMem(nBytesNeeded)
                  ptrPrinterInfo = Marshal.AllocHGlobal(nBytesNeeded)
                  ' The second GetPrinter fills in all the current settings, so all you
                  ' need to do is modify what you're interested in...
                  nRet = Convert.ToInt32(GetPrinter(hPrinter, 2, ptrPrinterInfo, nBytesNeeded, nJunk))
                  If nRet = 0 Then
                        lastError = Marshal.GetLastWin32Error()
                        Throw New Win32Exception(Marshal.GetLastWin32Error())
                  End If
                  pinfo = DirectCast(Marshal.PtrToStructure(ptrPrinterInfo, GetType(PRINTER_INFO_2)), PRINTER_INFO_2)
                  Dim Temp As New IntPtr()
                  If pinfo.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
                        sizeOfDevMode = DocumentProperties(IntPtr.Zero, hPrinter, PrinterName, ptrZero, ptrZero, 0)
                        ptrDM = Marshal.AllocCoTaskMem(sizeOfDevMode)
                        Dim i As Integer
                        i = DocumentProperties(IntPtr.Zero, hPrinter, PrinterName, ptrDM, ptrZero, DM_OUT_BUFFER)
                        If (i &lt; 0) OrElse (ptrDM = IntPtr.Zero) Then
                              'Cannot get the DEVMODE structure.
                              Throw New System.Exception("Cannot get DEVMODE data")
                        End If
                        pinfo.pDevMode = ptrDM
                  End If
                  intError = DocumentProperties(IntPtr.Zero, hPrinter, PrinterName, IntPtr.Zero, Temp, 0)
                  'IntPtr yDevModeData = Marshal.AllocCoTaskMem(i1);
                  yDevModeData = Marshal.AllocHGlobal(intError)
                  intError = DocumentProperties(IntPtr.Zero, hPrinter, PrinterName, yDevModeData, Temp, 2)
                  dm = DirectCast(Marshal.PtrToStructure(yDevModeData, GetType(DEVMODE)), DEVMODE)
                  'nRet = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, yDevModeData
                  ' , ref yDevModeData, (DM_IN_BUFFER | DM_OUT_BUFFER));
                  If (nRet = 0) OrElse (hPrinter = IntPtr.Zero) Then
                        lastError = Marshal.GetLastWin32Error()
                        'string myErrMsg = GetErrorMessage(lastError);
                        Throw New Win32Exception(Marshal.GetLastWin32Error())
                  End If
                  Return dm
            End If

      End Function
#End Region
End Class
General"The other problem is, the OpenPrinter does not work for network printers " Pin
Duncan Edwards Jones31-Jan-08 9:33
professionalDuncan Edwards Jones31-Jan-08 9:33 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.