Я пытаюсь обновить задание печати с новым набором свойств для структуры принтера DEVMODE
в моем приложении Win Forms на С#. В частности, лоток для печати.
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class DOCINFOA
{
[MarshalAs(UnmanagedType.LPStr)]
public string lpszDocName;
[MarshalAs(UnmanagedType.LPStr)]
public string lpszOutput;
[MarshalAs(UnmanagedType.LPStr)]
public string lpszDatatype;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
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 int Attributes;
public int Priority;
public int DefaultPriority;
public int StartTime;
public int UntilTime;
public int Status;
public int cJobs;
public int AveragePPM;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class DEVMODE
{
private const int CCHDEVICENAME = 32;
private const int CCHFORMNAME = 32;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)]
public string dmDeviceName;
public ushort dmSpecVersion;
public ushort dmDriverVersion;
public ushort dmSize;
public ushort dmDriverExtra;
public uint dmFields;
// values to set based on dmFields bits
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 int dmPositionX;
public int dmPositionY;
public uint dmDisplayOrientation;
public uint dmDisplayFixedOutput;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHFORMNAME)]
public string dmFormName;
public ushort dmLogPixels;
public uint dmBitsPerPel;
public uint dmPelsWidth;
public uint dmPelsHeight;
public uint dmDisplayFlags;
public uint dmDisplayFrequency;
public uint dmICMMethod;
public uint dmICMIntent;
public uint dmMediaType;
public uint dmDitherType;
public uint dmReserved1;
public uint dmReserved2;
public uint dmPanningWidth;
public uint dmPanningHeight;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class PRINTER_DEFAULTS
{
public IntPtr pDatatype;
public IntPtr pDevMode;
public int DesiredAccess;
}
[Flags]
public enum FModes
{
DM_SIZEOF = 0,
DM_UPDATE = 1,
DM_COPY = 2,
DM_PROMPT = 4,
DM_MODIFY = 8,
DM_OUT_DEFAULT = DM_UPDATE,
DM_OUT_BUFFER = DM_COPY,
DM_IN_PROMPT = DM_PROMPT,
DM_IN_BUFFER = DM_MODIFY,
}
[Flags]
public enum DevModeFields : uint
{
DM_ICMMETHOD = 0x10000,
DM_FORMNAME = 0x00010000,
DM_ICMINTENT = 0x04000000,
DM_MEDIATYPE = 0x08000000,
DM_DITHERTYPE = 0x10000000,
DM_COPIES = 0x00000100,
DM_DEFAULTSOURCE = 0x00000200,
DM_PRINT_QUALITY = 0x00000400,
DM_COLOR = 0x00000800,
DM_DUPLEX = 0x00001000,
DM_YRESOLUTION = 0x00002000,
DM_TTOPTION = 0x00004000,
DM_COLLATE = 0x00008000,
DM_ORIENTATION = 0x00000001,
DM_PAPERSIZE = 0x00000002,
DM_PAPERLENGTH = 0x00000004,
DM_PAPERWIDTH = 0x00000008,
DM_SCALE = 0x00000010
}
// DesiredAccess properties
const int PRINTER_ACCESS_ADMINISTER = 0x4;
const int PRINTER_ACCESS_USE = 0x8;
const int STANDARD_RIGHTS_REQUIRED = 0xF0000;
const int PRINTER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE);
public enum PaperSource
{
DMRES_HIGH = -4,
DMRES_MEDIUM = -3,
DMRES_LOW = -2,
DMRES_DRAFT = -1,
DMBIN_UPPER = 1,
DMBIN_LOWER = 2,
DMBIN_MIDDLE = 3,
DMBIN_MANUAL = 4,
DMBIN_ENVELOPE = 5,
DMBIN_ENVMANUAL = 6,
DMBIN_AUTO = 7,
DMBIN_TRACTOR = 8,
DMBIN_SMALLFMT = 9,
DMBIN_LARGEFMT = 10,
DMBIN_LARGECAPACITY = 11,
DMBIN_CASSETTE = 14,
DMBIN_FORMSOURCE = 15
}
PRINTER_DEFAULTS settings = new PRINTER_DEFAULTS
{
pDatatype = IntPtr.Zero,
pDevMode = IntPtr.Zero,
DesiredAccess = PRINTER_ACCESS_USE
};
int bytesNeeded = 0;
// get the printer handle
if (OpenPrinter(szPrinterName.Normalize(), out IntPtr hPrinter, settings))
{
// find out size needed for buffer first
GetPrinter(hPrinter, 2, IntPtr.Zero, 0, out bytesNeeded);
if (bytesNeeded > 0)
{
// allocate memory for the printer info
IntPtr pPrinterInfo = Marshal.AllocHGlobal(bytesNeeded);
// fetch pointer to printer info at level 2 (gives us DEVMODE data)
if (GetPrinter(hPrinter, 2, pPrinterInfo, bytesNeeded, out _))
{
// convert the pointer to the readable data
PRINTER_INFO_2 printerInfo = (PRINTER_INFO_2)Marshal.PtrToStructure(pPrinterInfo, typeof(PRINTER_INFO_2));
// for some reason it didnt fetch the DEVMODE data we need, try getting it elsewhere
if (true)
{
// find out size needed for buffer first
bytesNeeded = DocumentProperties(IntPtr.Zero, hPrinter, printerInfo.pPrinterName, IntPtr.Zero, IntPtr.Zero, (int)FModes.DM_SIZEOF);
if (bytesNeeded > 0)
{
// allocate memory for the DEVMODE info
IntPtr pDevMode = Marshal.AllocHGlobal(bytesNeeded);
// fetch pointer to DEVMODE info
int result = DocumentProperties(IntPtr.Zero, hPrinter, szPrinterName.Normalize(), pDevMode, IntPtr.Zero, (int)FModes.DM_OUT_BUFFER);
if (result > 0)
{
printerInfo.pDevMode = pDevMode;
}
}
}
// create the print job
DOCINFOA di = new DOCINFOA
{
lpszDocName = "My C#.NET RAW Document",
lpszDatatype = "RAW"
};
if (StartDocPrinter(hPrinter, 1, di))
{
if (StartPagePrinter(hPrinter))
{
// convert the pointer to readable data
DEVMODE dm = (DEVMODE)Marshal.PtrToStructure(printerInfo.pDevMode, typeof(DEVMODE));
// set new properties for printer
dm.dmFields |= (uint)DevModeFields.DM_DEFAULTSOURCE;
dm.dmDefaultSource = (short)PaperSource.DMBIN_UPPER;
Marshal.StructureToPtr(dm, printerInfo.pDevMode, false);
//overwrite the printers settings
int res = DocumentProperties(IntPtr.Zero, hPrinter, szPrinterName.Normalize(), printerInfo.pDevMode, printerInfo.pDevMode, (int)FModes.DM_IN_BUFFER | (int)FModes.DM_OUT_BUFFER);
if (res > 0)
{
WritePrinter(hPrinter, pBytes, dwCount, out _);
EndPagePrinter(hPrinter);
}
EndDocPrinter(hPrinter);
}
ClosePrinter(hPrinter);
}
}
}
Проблема, с которой я сталкиваюсь, заключается в том, что последний вызов DocumentProperties
не обновляет настройки задания принтера. Я проверил, что структура действительна, вставив вызов IsDevmodeValid
каждый раз, когда я читаю или пишу в структуру, и она возвращает ok. Я пытался установить структуру DEVMODE
как до, так и после настройки задания. Он просто не обновляет настройки, когда я просматриваю свойства заданий на печать.
Может ли кто-нибудь сказать мне, что мне здесь не хватает? К вашему сведению, он отлично печатает любые документы, но в лоток принтера по умолчанию.