|
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.
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)]
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);
#endregion
#region "Data structure"
[StructLayout(LayoutKind.Sequential)]
public struct PRINTER_DEFAULTS
{
public int pDatatype;
public int pDevMode;
public int 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;
Marshal.StructureToPtr(pinfo,ptrPrinterInfo,true);
lastError = Marshal.GetLastWin32Error();
nRet = Convert.ToInt16(SetPrinter(hPrinter, 2, ptrPrinterInfo, 0));
if (nRet == 0)
{
lastError = Marshal.GetLastWin32Error();
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
{
{ptrPrinterIn fo = Marshal.AllocCoTaskMem(nBytesNeeded)};
ptrPrinterInfo = Marshal.AllocHGlobal(nBytesNeeded);
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)
{
IntPtr ptrZero = IntPtr.Zero;
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))
{
throw new System.Exception("Cannot get DEVMODE data");
}
pinfo.pDevMode = ptrDM;
}
intError = DocumentProperties(IntPtr.Zero, hPrinter,
PrinterName, IntPtr.Zero , ref Temp , 0);
yDevModeData= Marshal.AllocHGlobal(intError);
intError = DocumentProperties(IntPtr.Zero, hPrinter,
PrinterName, yDevModeData , ref Temp , 2);
dm = (DEVMODE)Marshal.PtrToStructure(yDevModeData, typeof(DEVMODE));
if ((nRet == 0) || (hPrinter == IntPtr.Zero))
{
lastError = Marshal.GetLastWin32Error();
throw new Win32Exception(Marshal.GetLastWin32Error());
}
return dm;
}
#endregion
}}
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 39 (Total in Forum: 39) (Refresh) | FirstPrevNext |
|
 |
|
|
Well - it does, but you may need to specify PRINTER_DEFAULTS.DesiredAccess -SERVER_ALL_ACCESS instead or PRINTER_ALL_ACCESS.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Surely...I'll have to explain in VB.NET though...
When you call OpenPrinter you can pass a PRINTER_DEFAULTS structure to specify the desired access you want on that printer:
<DllImport("winspool.drv", EntryPoint:="OpenPrinter", _ SetLastError:=True, CharSet:=CharSet.Ansi, _ ExactSpelling:=False, _ CallingConvention:=CallingConvention.StdCall)> _ Public Function OpenPrinter(<InAttribute()> ByVal pPrinterName As String, _ <OutAttribute()> ByRef phPrinter As Int32, _ <InAttribute(), MarshalAs(UnmanagedType.LPStruct)> ByVal pDefault As PRINTER_DEFAULTS _ ) As Boolean
End Function
This structure is:-
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _ Friend Class PRINTER_DEFAULTS Public lpDataType As Int32 Public lpDevMode As Int32 <MarshalAs(UnmanagedType.U4)> Public DesiredAccess As PrinterAccessRights
End Class
where the DesiredAccess is a combination of:-
<FlagsAttribute()> _ Public Enum PrinterAccessRights ' READ_CONTROL - Allowed to read printer information READ_CONTROL = &H20000 ' WRITE_DAC - Allowed to write device access control info WRITE_DAC = &H40000 ' WRITE_OWNER - Allowed to change the object owner WRITE_OWNER = &H80000 ' SERVER_ACCESS_ADMINISTER SERVER_ACCESS_ADMINISTER = &H1 ' SERVER_ACCESS_ENUMERATE SERVER_ACCESS_ENUMERATE = &H2 ' PRINTER_ACCESS_ADMINISTER Allows administration of a printer PRINTER_ACCESS_ADMINISTER = &H4 ' PRINTER_ACCESS_USE Allows printer general use (printing, querying) PRINTER_ACCESS_USE = &H8 ' PRINTER_ALL_ACCESS Allows use and administration. PRINTER_ALL_ACCESS = &HF000C ' SERVER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE) SERVER_ALL_ACCESS = &HF0003 End Enum
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi Duncan,
I modified my program according to your reply and tried using SERVER_ALL_ACCESS, but I still get the "ACCESS IS DENIED" error. Was your program working fine with the network printer?
Thank you.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
It was (is) - do you have modify rights on the server printer from Control Panel? If not, try SERVER_ACCESS_USE
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
I have use this code, but Status field after GetPrinter function call is always 0. Why? How can I solve it?
Thanks, Ana
Ana
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
Yes, I have the same result. Reason is:
http://support.microsoft.com/kb/160129[^] says:
There is one fundamental premise that must be true to determine the state of a physical printer: the Spooler must be attempting to send a print job to the physical printer. This is the only time the state of the printer is reported by the port monitor.
Luc Pattyn
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I cannot change printer settings like other guys. I do get my printer default settings with API you have provided but when I set my own parameters they do not reflect in printer settings. I cannot figiure out what is going on?
Is anybody here who can provide working sample?
P.S. Don't you should set dmFlags when updating DEVMODE? By the way it does not helps.
Best regards.
Bartosz Węgielewski
|
| Sign In·View Thread·PermaLink | 1.83/5 (3 votes) |
|
|
|
 |
|
|
Hi , This code is not working for my application. I am using ProcessStartInfo class to print file. So i am changing printer settings globally. But it is taking all default printer settings.
I wonder Y.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
In the code below, aren't the first two lastError = Marshal.GetLastWin32Error(); lines are unnecessary? (Since return values are not used)
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()); }
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I noticed you weren't marshalling the extra printer-specific information designated w/ DEVMODE.dmDriverExtra. Did you figure out a clever way of doing this?
|
| Sign In·View Thread·PermaLink | 4.13/5 (5 votes) |
|
|
|
 |
|
|
First of all, great work - there aren't many articles out there on doing this in .NET (in fact yours might be the only one!)
Been testing this class quite extensively and I noticed a probable *bug*(?) on my machine which is on WinXP.
Background: I'm using IE to programatically render and print web pages to PDF with the PDF995 print driver which can be found at (www.pdf995.com)
I've populated a list of page sizes defined for the printer and am setting them in code before sending the job to print. I noticed that some print size selections work and some didn't.
That was odd but then I noticed that only non-custom kinds of page settings were applied. Custom page settings result in the driver falling back to a fixed default size.
However, if I manually go through IE and set the page size in the page settings dialog, somehow they work! So IE must be doing something differently that works.
Been looking around for hours but there's not much info on the 'net regarding this... anyone faced a similar problem or better still, solved it?
Any ideas anyone?
paul
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
Hi
I'm trying to execute the code u've given. but where ever I change the setting of the printer (like... papersource, orientation...) it is not getting reflected into my printer driver properties. How do I make those settings permenent ?
karthik
|
| Sign In·View Thread·PermaLink | 2.00/5 (3 votes) |
|
|
|
 |
|
|
This is just a helpful hint. I check the values of the enumerations defined in System.Drawing.Printing, and there values map directly to the short values in the DEVMODE structure. Knowing this I modified the above code to work off of the PageSettings, and PaperSettings rather than using the custom PrinterData class that was defined in on of the threads.
Here is the modifications that I made based on reusing the enumeration/classes already in the .NET framework:
using System; using System.Runtime.InteropServices; using System.Drawing.Printing; using System.ComponentModel; using NowDocs.Util;
namespace CustomprinterSettings { #region "Data structure" #region PRINTER_DEFAULTS [StructLayout(LayoutKind.Sequential)] public struct PRINTER_DEFAULTS { public int pDatatype; public int pDevMode; public int DesiredAccess; } #endregion PRINTER_DEFAULTS
#region PRINTER_INFO_2 [StructLayout(LayoutKind.Sequential)] 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; } #endregion PRINTER_INFO_2
#region DEVMODE [StructLayout(LayoutKind.Sequential)] public struct DEVMODE { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] 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 = 32)] public string dmFormName; public short dmUnusedPadding; public short dmBitsPerPel; public int dmPelsWidth; public int dmPelsHeight; public int dmDisplayFlags; public int dmDisplayFrequency; } #endregion DEVMODE
#endregion "Data structure"
#region PrinterConfiguration public class PrinterConfiguration {
#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 _Devmode; 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)] 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);
#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"
#region ChangePrinterPaperSize(string PrinterName,PaperSize paperSize) public bool ChangePrinterPaperSize (string printerName, PaperSize paperSize) { try { _Devmode = this.GetPrinterSettings( printerName); _Devmode.dmPaperSize =(short)paperSize.Kind; if (paperSize.Kind == PaperKind.Custom) { _Devmode.dmPaperWidth = Convert.ToInt16 ((double)Math.Round (((Convert.ToDouble (pageSettings.PaperSize.Width))/100D)*25.4D*10D)); _Devmode.dmPaperLength = Convert.ToInt16 ((double)Math.Round ((Convert.ToDouble (pageSettings.PaperSize.Height)/100D)*25.4D*10D)); } Marshal.StructureToPtr( _Devmode,_YDevModeData,true); _pinfo.pDevMode = _YDevModeData; _pinfo.pSecurityDescriptor = IntPtr.Zero; 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()); } } finally { if (_hPrinter != IntPtr.Zero) {
ClosePrinter(_hPrinter); } }
return Convert.ToBoolean(_NRet); } #endregion ChangePrinterPaperSize(string PrinterName,PrinterData PS)
#region ChangePrinterOrientation(string PrinterName,bool landscape) public bool ChangePrinterOrientation (string printerName, bool landscape) { try { _Devmode = this.GetPrinterSettings( printerName); _Devmode.dmOrientation = (short)((landscape)?2:1); Marshal.StructureToPtr( _Devmode,_YDevModeData,true); _pinfo.pDevMode = _YDevModeData; _pinfo.pSecurityDescriptor = IntPtr.Zero; 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()); } } finally { if (_hPrinter != IntPtr.Zero) {
ClosePrinter(_hPrinter); } }
return Convert.ToBoolean(_NRet); } #endregion ChangePrinterOrientation(string PrinterName,bool landscape)
#region ChangePrinterSetting(string PrinterName,PageSettings pageSettings) public bool ChangePrinterSetting(string PrinterName,PageSettings pageSettings) { try { _Devmode = this.GetPrinterSettings( PrinterName); _Devmode.dmDefaultSource =(short)pageSettings.PaperSource.Kind; _Devmode.dmOrientation = (short)((pageSettings.Landscape)?2:1); _Devmode.dmPaperSize =(short)pageSettings.PaperSize.Kind; if (pageSettings.PaperSize.Kind == PaperKind.Custom) { _Devmode.dmPaperWidth = Convert.ToInt16 ((double)Math.Round (((Convert.ToDouble (pageSettings.PaperSize.Width))/100D)*25.4D*10D)); _Devmode.dmPaperLength = Convert.ToInt16 ((double)Math.Round ((Convert.ToDouble (pageSettings.PaperSize.Height)/100D)*25.4D*10D)); } Marshal.StructureToPtr( _Devmode,_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()); } } finally { if (_hPrinter != IntPtr.Zero) {
ClosePrinter(_hPrinter); } } return Convert.ToBoolean(_NRet); }
#endregion ChangePrinterSetting(string PrinterName,PageSettings pageSettings) #region ChangePrinterSetting(string PrinterName,PageSettings pageSettings, Duplex duplex) public bool ChangePrinterSetting(string PrinterName,PageSettings pageSettings, Duplex duplex) { try { _Devmode = this.GetPrinterSettings( PrinterName); _Devmode.dmDefaultSource =(short)pageSettings.PaperSource.Kind; _Devmode.dmOrientation = (short)((pageSettings.Landscape)?2:1); _Devmode.dmPaperSize =(short)pageSettings.PaperSize.Kind; if (pageSettings.PaperSize.Kind == PaperKind.Custom) { _Devmode.dmPaperWidth = Convert.ToInt16 ((double)Math.Round (((Convert.ToDouble (pageSettings.PaperSize.Width))/100D)*25.4D*10D)); _Devmode.dmPaperLength = Convert.ToInt16 ((double)Math.Round ((Convert.ToDouble (pageSettings.PaperSize.Height)/100D)*25.4D*10D)); } _Devmode.dmDuplex = (short)duplex; Marshal.StructureToPtr( _Devmode,_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()); } } finally { if (_hPrinter != IntPtr.Zero) {
ClosePrinter(_hPrinter); } } return Convert.ToBoolean(_NRet); }
#endregion ChangePrinterSetting(string PrinterName,PageSettings pageSettings, bool landscape)
#region ChangePrinterSetting(string PrinterName,Duplex duplex) public bool ChangePrinterSetting(string PrinterName,Duplex duplex) { try { _Devmode = this.GetPrinterSettings( PrinterName); _Devmode.dmDuplex = (short)duplex; Marshal.StructureToPtr( _Devmode,_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()); } } finally { if (_hPrinter != IntPtr.Zero) {
ClosePrinter(_hPrinter); } } return Convert.ToBoolean(_NRet); }
#endregion ChangePrinterSetting(string PrinterName,Duplex duplex)
#region GetPrinterSettings(string PrinterName) private DEVMODE GetPrinterSettings(string PrinterName) { DEVMODE devmode; 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); devmode = (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(); throw new Win32Exception(Marshal.GetLastWin32Error()); } return devmode; } } #endregion GetPrinterSettings(string PrinterName)
#endregion "Function to change printer settings" } #endregion PrinterConfiguration }
|
| Sign In·View Thread·PermaLink | 1.56/5 (3 votes) |
|
|
|
 |
|
|
Your alternative to the codes in the thread is quite helpful. But I wonder on how to code to set the dmFormName of DEVMODE structure and use the custom size form as the current form for the Device Context (DC) of the printer without changing current default setting of the printer in C#. Can you give me some hints on that? Thank you.
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
Thanks for this. I wanted some code to change the default paper bin of a printer (so I could get Word to use it). After scouring the internet for a solution I finally came across this article and then your modifications.
I had this code working in minutes.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 | | |