|
two changes required:
public struct PRINTER_DEFAULTS
{
public IntPtr pDatatype;
public IntPtr pDevMode;
public int DesiredAccess;
}
PrinterValues.pDatatype = IntPtr.Zero;
PrinterValues.pDevMode = IntPtr.Zero;
|
|
|
|
|
Hi,
Thank for your helpful article,
is there is an option to change the property "Print spooled document first" in the Printer Properties - Advanced?
with this code or another?
|
|
|
|
|
First of all, thanks for sharing this, along with the comments everything works as expected, except the
fact that if i target the build on 64 bits, the code crashes here:
nRet = Convert.ToInt32(OpenPrinter(PrinterName, out hPrinter, PrinterValues));
Has anyone encountered this problem and knows how to fix it? From what i read, it's something related to the data type which doesn't return the same value depending of the targeted architecture.
Thanks in advance.
|
|
|
|
|
I've tried changing the printer settings but it doesn't work. It always defaults to what the printer's settings are.
I am working for printer Laser jet Pro M403dn and this is local printer.
I saw the came problem in comments below. Please help.
|
|
|
|
|
Needed to create the printerdata class
public class PrinterData
{
public PrinterData()
{
Duplex = 1;
source = 1;
Orientation = 1;
Size = 1;
}
public int Duplex { get; set; }
public int source { get; set; }
public int Orientation { get; set; }
public int Size { get; set; }
}
Changed code from:
{ptrPrinterIn fo = Marshal.AllocCoTaskMem(nBytesNeeded); };
to
{
Marshal.AllocCoTaskMem(nBytesNeeded); };
System would crash if you didn't change:
Marshal.StructureToPtr(pinfo, ptrPrinterInfo, true);
to
Marshal.StructureToPtr(pinfo, ptrPrinterInfo, false);
Working on windows 10 OS.
|
|
|
|
|
After an upgrade to windows 7 this code does not effect printing. A line of code failed until I added a memory allocation call.
ptrPrinterInfo = Marshal.AllocHGlobal(yDevModeData);
Marshal.StructureToPtr(pinfo, ptrPrinterInfo, true);
The StructureToPtr command would throw an exception in win7 without the allocation call; but now the printing is still not effected.
While debugging I can see printer settings changing but the changes are not shown when the doc actually comes off the printer.
Any ideas?
|
|
|
|
|
I tested it and it worked, I just modified to get a duplex printing and it worked well on windows 8, the printer printed in both sides of the sheet.
|
|
|
|
|
|
public class PrinterData
{
public int Duplex { get; set; }
public int Source { get; set; }
public int Orientation { get; set; }
public int Size { get; set; }
}

|
|
|
|
|
I see dmCollate but I can't find where you used it. I am trying to implement printing of multiple copies with collate to be turned on and off. Can you please explain more on this?
|
|
|
|
|
Hi there,
has anybody a samplecode for changeing the orientage for a printer for the system?
thx
|
|
|
|
|
|
We have Dymo labelwriter 450 turbo printer. Where the paper size is as per the printer. Using above given code and following code I am trying to change printer settings. but it seems only Orientations (Landscape, Portrait) gets changed. But I am not able to change printer settings like PaperSize, PrintQuality. Also when I try to change settings of default "Microsoft XPS Document Writer" printer. The code can set PaperSize through program. Can anybody please help me to make the above code work to set Advance printer properties like PaperSize, PrintQuality? And why above code is not working for our dymo printer? The printer is attached locally to machine
PrinterData pd = new PrinterData();
pd.Duplex = PageDuplex.DMDUP_VERTICAL;
pd.Orientation = PageOrientation.DMORIENT_PORTRAIT;
pd.Size = PaperSize.DMPAPER_LETTER;
pd.source = PaperSource.DMBIN_AUTO;
ChangePrinterSetting(szPrinterName, pd);
modified 21-Dec-11 10:06am.
|
|
|
|
|
hello..
How do I'm get the status printer from the EPSON STATUS MONITOR 3 ?, I've tried to detect the status direct from the driver, not from windows,
but I just get the status from the windows, not from DRIVER, the difference :
if from the windows after the printing is executed then the status is successful automatically, although printing not yet finished.
Well, how can I'm communication with the printer driver
I'm using printer EPSON LX-300+II, delphi2010, windows7.
does anyone ever have problems like me ???
I'm also received Example snippet code if you've used other programming languages, eg : C
Please help me.
thank...
|
|
|
|
|
Hi,
after 2 days of trial and error (and reading tons of posts in various forums) I found a solution to the network printer problem.
First of all, you have to use
private const int PRINTER_ACCESS_USE = 0x8;
as setting for DesiredAccess in the PRINTER_DEFAULTS-struct -> A "standard" user won't get any admin rights on a network printer, resulting in the "Access denied" exception.
With this change the exception goes away, but you still won't be able to call SetPrinter for a network printer. Inspired by this post http://vbcity.com/forums/t/36391.aspx[^] I replaced the PRINTER_INFO_2-struct with PRINTER_INFO_9:
[StructLayout(LayoutKind.Sequential)]
public struct PRINTER_INFO_9
{
public IntPtr DevMode;
}
and changed corresponding statements to use the new structure (GetPrinter, SetPrinter and Marshal.PtrToStructure to get the printerInfo)
With this changes you should be able to access and change network printers.
|
|
|
|
|
Thanks mate. This solution actually did work for network printers for me..
In the article's code, though I couldn't figure out in the article code, what PrinterData means, but I got rid of it, figured out valid values of duplex setting, and used PRINTER_INFO_9 and used 9 instead of 2 for memory allocation and duplex setting worked like a charm.
|
|
|
|
|
Hi. i am new in the interface of tge printer withy C# application so can you please help me.
My task is the real time printing or drawing on paper.
It is not the one time output of the page from the printer but actually the page would be divided into portions, like after reading data to be printed on certain portion (say first portion) of the paper i send it to the printer to be printed and the printer outputs only that portion of the paper for which i have given the data. meanwhile i read data for the next portion and then give it to the printer which then prints the second portion of it. and likewise it goes on.
Presently i am using graphics libraray of C# but it is only for the single time output only. Now kindly tel me what can i do to accomplish my goal. I would be very thankful if you tel me an easy way. also please tel me the libraraies which i am needed to install and use.
Here is the code which i am presently using but it is for one time page input output only.
using System.Drawing.Printing;
namespace BA2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
PrintDialog printDialog1 = new PrintDialog();
printDialog1.UseEXDialog = true;
printDialog1.Document = printDocument1;
DialogResult result = printDialog1.ShowDialog();
if (result == DialogResult.OK)
{
printDocument1.Print();
}
}
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
Pen blackPen = new Pen(Color.Blue, 1);
Point[] points =
{
new Point(10,100),
new Point(20,90),
new Point(30,80),
new Point(40,74),
new Point(50,68),
};
e.Graphics.DrawLines(blackPen, points);
}
.
.
Kindly help me. I am waiting for the response.
|
|
|
|
|
Hi can any body please help me. I am working on C# but i havent ever worked on printer settings or getting printer DLLs or using DEVMODE. i have just recently read about it. I want to know that how can i use it i.e. what are the steps for getting started with operating or controlling the printer settings. what do i need to install first and what libraray is needed to be added first and then how to use it further? can you please help me as soon as possible. I am waiting for the response.
|
|
|
|
|
Hi all,
Seems that this piece of code is great! But...
How do you make the setPrinter method work with networkprinters?
|
|
|
|
|
PrinterData pd = new PrinterData();
pd.Duplex = PageDuplex.DMDUP_VERTICAL;
pd.Orientation = PageOrientation.DMORIENT_PORTRAIT;
pd.Size = PaperSize.DMPAPER_LETTER;
pd.source = PaperSource.DMBIN_AUTO;
ChangePrinterSetting(szPrinterName, pd);
Does not work, the printer always uses its default settings. Please help.
|
|
|
|
|
I've tried changing the printer settings but it doesn't work. It always defaults to what the printer's settings are. Please help
|
|
|
|
|
works fine for me 
|
|
|
|
|
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"
<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)]
' 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 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
'[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"
<StructLayout(LayoutKind.Sequential)> _
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;
' }
<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 "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) < 1) OrElse (DirectCast(PS.Duplex, Short) > 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 <> 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 <= 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 < 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
|
|
|
|
|
Well - it does, but you may need to specify PRINTER_DEFAULTS.DesiredAccess -SERVER_ALL_ACCESS instead or PRINTER_ALL_ACCESS.
|
|
|
|
|
Can you explain this with more detail please?
|
|
|
|
|