<PackageReference Include="System.Drawing.Common" Version="10.0.0-preview.7.25380.108" />

PrinterSettings

public class PrinterSettings : ICloneable
Specifies information about how a document is printed, including the printer that prints it, when printing from a Windows Forms application.
using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Windows.Win32; using Windows.Win32.Foundation; using Windows.Win32.Graphics.Gdi; using Windows.Win32.Graphics.Printing; using Windows.Win32.Storage.Xps; using Windows.Win32.System.Memory; using Windows.Win32.UI.Controls.Dialogs; namespace System.Drawing.Printing { [NullableContext(1)] [Nullable(0)] public class PrinterSettings : ICloneable { [NullableContext(2)] [Nullable(0)] private sealed class ArrayEnumerator : IEnumerator { [Nullable(1)] private readonly object[] _array; private readonly int _endIndex; private int _index; private object _item; public object Current => _item; [NullableContext(1)] public ArrayEnumerator(object[] array, int count) { _array = array; _endIndex = count; } public bool MoveNext() { if (_index >= _endIndex) return false; _item = _array[_index++]; return true; } public void Reset() { _index = 0; _item = null; } } [Nullable(0)] public class PaperSizeCollection : ICollection, IEnumerable { private PaperSize[] _array; public int Count => _array.Length; public virtual PaperSize this[int index] { get { return _array[index]; } } int ICollection.Count { get { return Count; } } bool ICollection.IsSynchronized { get { return false; } } object ICollection.SyncRoot { get { return this; } } public PaperSizeCollection(PaperSize[] array) { _array = array; } public IEnumerator GetEnumerator() { object[] array = _array; return new ArrayEnumerator(array, Count); } void ICollection.CopyTo(Array array, int index) { Array.Copy(_array, index, array, 0, _array.Length); } public void CopyTo(PaperSize[] paperSizes, int index) { Array.Copy(_array, index, paperSizes, 0, _array.Length); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } [EditorBrowsable(EditorBrowsableState.Never)] public int Add(PaperSize paperSize) { PaperSize[] array = new PaperSize[Count + 1]; ((ICollection)this).CopyTo((Array)array, 0); array[Count] = paperSize; _array = array; return Count; } } [Nullable(0)] public class PaperSourceCollection : ICollection, IEnumerable { private PaperSource[] _array; public int Count => _array.Length; public virtual PaperSource this[int index] { get { return _array[index]; } } int ICollection.Count { get { return Count; } } bool ICollection.IsSynchronized { get { return false; } } object ICollection.SyncRoot { get { return this; } } public PaperSourceCollection(PaperSource[] array) { _array = array; } public IEnumerator GetEnumerator() { object[] array = _array; return new ArrayEnumerator(array, Count); } void ICollection.CopyTo(Array array, int index) { Array.Copy(_array, index, array, 0, _array.Length); } public void CopyTo(PaperSource[] paperSources, int index) { Array.Copy(_array, index, paperSources, 0, _array.Length); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } [EditorBrowsable(EditorBrowsableState.Never)] public int Add(PaperSource paperSource) { PaperSource[] array = new PaperSource[Count + 1]; ((ICollection)this).CopyTo((Array)array, 0); array[Count] = paperSource; _array = array; return Count; } } [Nullable(0)] public class PrinterResolutionCollection : ICollection, IEnumerable { private PrinterResolution[] _array; public int Count => _array.Length; public virtual PrinterResolution this[int index] { get { return _array[index]; } } int ICollection.Count { get { return Count; } } bool ICollection.IsSynchronized { get { return false; } } object ICollection.SyncRoot { get { return this; } } public PrinterResolutionCollection(PrinterResolution[] array) { _array = array; } public IEnumerator GetEnumerator() { object[] array = _array; return new ArrayEnumerator(array, Count); } void ICollection.CopyTo(Array array, int index) { Array.Copy(_array, index, array, 0, _array.Length); } public void CopyTo(PrinterResolution[] printerResolutions, int index) { Array.Copy(_array, index, printerResolutions, 0, _array.Length); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } [EditorBrowsable(EditorBrowsableState.Never)] public int Add(PrinterResolution printerResolution) { PrinterResolution[] array = new PrinterResolution[Count + 1]; ((ICollection)this).CopyTo((Array)array, 0); array[Count] = printerResolution; _array = array; return Count; } } [Nullable(0)] public class StringCollection : ICollection, IEnumerable, IEnumerable<string> { private readonly List<string> _list; public int Count => _list.Count; public virtual string this[int index] { get { return _list[index]; } } int ICollection.Count { get { return Count; } } bool ICollection.IsSynchronized { get { return false; } } object ICollection.SyncRoot { get { return this; } } public StringCollection(string[] array) { _list = array.ToList(); } public IEnumerator GetEnumerator() { return ((IEnumerable)_list).GetEnumerator(); } void ICollection.CopyTo(Array array, int index) { ((ICollection)_list).CopyTo(array, index); } public void CopyTo(string[] strings, int index) { ((ICollection)_list).CopyTo((Array)strings, index); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } [EditorBrowsable(EditorBrowsableState.Never)] public int Add(string value) { _list.Add(value); return _list.Count; } IEnumerator<string> IEnumerable<string>.GetEnumerator() { return _list.GetEnumerator(); } } [Nullable(2)] private string _printerName; private string _driverName = ""; private ushort _extraBytes; [Nullable(2)] private byte[] _extraInfo; private short _copies = -1; private Duplex _duplex = Duplex.Default; private TriState _collate = TriState.Default; private readonly PageSettings _defaultPageSettings; private int _fromPage; private int _toPage; private int _maxPage = 9999; private int _minPage; private PrintRange _printRange; private ushort _devmodeBytes; [Nullable(2)] private byte[] _cachedDevmode; public bool CanDuplex => DeviceCapabilities(PRINTER_DEVICE_CAPABILITIES.DC_DUPLEX, null, -1) == 1; public short Copies { get { if (_copies == -1) return GetModeField(ModeField.Copies, 1); return _copies; } set { if (value < 0) throw new ArgumentException(System.SR.Format(System.SR.InvalidLowBoundArgumentEx, "value", value, 0)); _copies = value; } } public bool Collate { get { if (!_collate.IsDefault) return (bool)_collate; return GetModeField(ModeField.Collate, 0) == 1; } set { _collate = value; } } public PageSettings DefaultPageSettings => _defaultPageSettings; internal string DriverName => _driverName; public Duplex Duplex { get { if (_duplex == Duplex.Default) return (Duplex)GetModeField(ModeField.Duplex, 1); return _duplex; } set { if ((value < Duplex.Default || value > Duplex.Horizontal) ? true : false) throw new InvalidEnumArgumentException("value", (int)value, typeof(Duplex)); _duplex = value; } } public int FromPage { get { return _fromPage; } set { if (value < 0) throw new ArgumentException(System.SR.Format(System.SR.InvalidLowBoundArgumentEx, "value", value, 0)); _fromPage = value; } } public unsafe static StringCollection InstalledPrinters { get { uint minimumLength = default(uint); uint num = default(uint); if (!(bool)PInvoke.EnumPrinters(6, null, 4, null, 0, &minimumLength, &num)) { WIN32_ERROR lastPInvokeError = (WIN32_ERROR)Marshal.GetLastPInvokeError(); if (lastPInvokeError != WIN32_ERROR.ERROR_INSUFFICIENT_BUFFER) throw new Win32Exception((int)lastPInvokeError); } BufferScope<byte> bufferScope = new BufferScope<byte>((int)minimumLength); try { fixed (byte* ptr = &bufferScope.GetPinnableReference()) { if (!(bool)PInvoke.EnumPrinters(6, null, 4, ptr, (uint)bufferScope.Length, &minimumLength, &num)) throw new Win32Exception(); string[] array = new string[num]; ReadOnlySpan<PRINTER_INFO_4W> readOnlySpan = new ReadOnlySpan<PRINTER_INFO_4W>(ptr, (int)num); for (int i = 0; i < num; i++) { array[i] = new string(readOnlySpan[i].pPrinterName); } return new StringCollection(array); } } finally { bufferScope.Dispose(); } } } public bool IsDefaultPrinter { get { if (_printerName != null) return _printerName == GetDefaultPrinterName(); return true; } } public bool IsPlotter => (long)GetDeviceCaps(GET_DEVICE_CAPS_INDEX.TECHNOLOGY) == 0; public bool IsValid => DeviceCapabilities(PRINTER_DEVICE_CAPABILITIES.DC_COPIES, null, -1) != -1; public int LandscapeAngle => DeviceCapabilities(PRINTER_DEVICE_CAPABILITIES.DC_ORIENTATION, null, 0); public int MaximumCopies => DeviceCapabilities(PRINTER_DEVICE_CAPABILITIES.DC_COPIES, null, 1); public int MaximumPage { get { return _maxPage; } set { if (value < 0) throw new ArgumentException(System.SR.Format(System.SR.InvalidLowBoundArgumentEx, "value", value, 0)); _maxPage = value; } } public int MinimumPage { get { return _minPage; } set { if (value < 0) throw new ArgumentException(System.SR.Format(System.SR.InvalidLowBoundArgumentEx, "value", value, 0)); _minPage = value; } } internal string OutputPort { get; set; } = ""; public string PrintFileName { get { return OutputPort; } set { if (string.IsNullOrEmpty(value)) throw new ArgumentNullException(value); OutputPort = value; } } public PaperSizeCollection PaperSizes => new PaperSizeCollection(Get_PaperSizes()); public PaperSourceCollection PaperSources => new PaperSourceCollection(Get_PaperSources()); internal bool PrintDialogDisplayed { get; set; } public PrintRange PrintRange { get { return _printRange; } set { if (!Enum.IsDefined(value)) throw new InvalidEnumArgumentException("value", (int)value, typeof(PrintRange)); _printRange = value; } } public bool PrintToFile { get; set; } public string PrinterName { get { return PrinterNameInternal; } set { PrinterNameInternal = value; } } private string PrinterNameInternal { get { return _printerName ?? GetDefaultPrinterName(); } set { _cachedDevmode = null; _extraInfo = null; _printerName = value; } } public PrinterResolutionCollection PrinterResolutions => new PrinterResolutionCollection(Get_PrinterResolutions()); public bool SupportsColor => DeviceCapabilities(PRINTER_DEVICE_CAPABILITIES.DC_COLORDEVICE, null, -1) == 1; public int ToPage { get { return _toPage; } set { if (value < 0) throw new ArgumentException(System.SR.Format(System.SR.InvalidLowBoundArgumentEx, "value", value, 0)); _toPage = value; } } public PrinterSettings() { _defaultPageSettings = new PageSettings(this); } public bool IsDirectPrintingSupported(ImageFormat imageFormat) { if (imageFormat.Equals(ImageFormat.Jpeg) || imageFormat.Equals(ImageFormat.Png)) { CreateDcScope scope = CreateInformationContext(DefaultPageSettings); try { int escapeFunction; return IsDirectPrintingSupported((HDC)ref scope, imageFormat, out escapeFunction); } finally { scope.Dispose(); } } return false; } private unsafe static bool IsDirectPrintingSupported(HDC hdc, ImageFormat imageFormat, out int escapeFunction) { escapeFunction = (imageFormat.Equals(ImageFormat.Jpeg) ? 4119 : 4120); fixed (int* ptr = &escapeFunction) { int* ptr2 = ptr; return PInvoke.ExtEscape(hdc, 8, 4, (PCSTR)(byte*)(&ptr2), 0, null) != 0; } } public unsafe bool IsDirectPrintingSupported(Image image) { ImageFormat rawFormat = image.RawFormat; if (rawFormat.Equals(ImageFormat.Jpeg) || rawFormat.Equals(ImageFormat.Png)) { CreateDcScope scope = CreateInformationContext(DefaultPageSettings); try { if (IsDirectPrintingSupported((HDC)ref scope, rawFormat, out int escapeFunction)) { using (MemoryStream memoryStream = new MemoryStream()) { image.Save(memoryStream, image.RawFormat); byte[] array = memoryStream.ToArray(); fixed (byte* value = array) { uint num = default(uint); return PInvoke.ExtEscape((HDC)ref scope, escapeFunction, array.Length, (PCSTR)value, 4, (byte*)(&num)) == 1; } } } return false; } finally { scope.Dispose(); } } return false; } public object Clone() { PrinterSettings obj = (PrinterSettings)MemberwiseClone(); obj.PrintDialogDisplayed = false; return obj; } internal CreateDcScope CreateDeviceContext(PageSettings pageSettings) { HGLOBAL hdevmodeInternal = GetHdevmodeInternal(); try { pageSettings.CopyToHdevmode(hdevmodeInternal); return CreateDeviceContext(hdevmodeInternal); } finally { PInvokeCore.GlobalFree(hdevmodeInternal); } } internal unsafe CreateDcScope CreateDeviceContext(HGLOBAL hdevmode) { DEVMODEW* lpInitData = (DEVMODEW*)PInvokeCore.GlobalLock(hdevmode); CreateDcScope result = new CreateDcScope(DriverName, PrinterNameInternal, lpInitData, false); PInvokeCore.GlobalUnlock(hdevmode); return result; } internal CreateDcScope CreateInformationContext(PageSettings pageSettings) { HGLOBAL hdevmodeInternal = GetHdevmodeInternal(); try { pageSettings.CopyToHdevmode(hdevmodeInternal); return CreateInformationContext(hdevmodeInternal); } finally { PInvokeCore.GlobalFree(hdevmodeInternal); } } internal unsafe CreateDcScope CreateInformationContext(HGLOBAL hdevmode) { void* lpInitData = PInvokeCore.GlobalLock(hdevmode); CreateDcScope result = new CreateDcScope(DriverName, PrinterNameInternal, (DEVMODEW*)lpInitData, true); PInvokeCore.GlobalUnlock(hdevmode); return result; } public Graphics CreateMeasurementGraphics() { return CreateMeasurementGraphics(DefaultPageSettings); } public Graphics CreateMeasurementGraphics(bool honorOriginAtMargins) { Graphics graphics = CreateMeasurementGraphics(); if (honorOriginAtMargins) { graphics.TranslateTransform(0 - _defaultPageSettings.HardMarginX, 0 - _defaultPageSettings.HardMarginY); graphics.TranslateTransform((float)_defaultPageSettings.Margins.Left, (float)_defaultPageSettings.Margins.Top); } return graphics; } public Graphics CreateMeasurementGraphics(PageSettings pageSettings) { CreateDcScope scope = CreateDeviceContext(pageSettings); Graphics graphics = Graphics.FromHdcInternal((IntPtr)ref scope); graphics.PrintingHelper = new HdcHandle(scope); return graphics; } public Graphics CreateMeasurementGraphics(PageSettings pageSettings, bool honorOriginAtMargins) { Graphics graphics = CreateMeasurementGraphics(); if (honorOriginAtMargins) { graphics.TranslateTransform(0 - pageSettings.HardMarginX, 0 - pageSettings.HardMarginY); graphics.TranslateTransform((float)pageSettings.Margins.Left, (float)pageSettings.Margins.Top); } return graphics; } [NullableContext(0)] private unsafe int DeviceCapabilities(PRINTER_DEVICE_CAPABILITIES capability, void* output = default(void*), int defaultValue = -1) { return FastDeviceCapabilities(capability, PrinterName, output, defaultValue); } [NullableContext(0)] private unsafe static int FastDeviceCapabilities(PRINTER_DEVICE_CAPABILITIES capability, [Nullable(1)] string printerName, void* output = default(void*), int defaultValue = -1) { IntPtr value; if (printerName == null) value = (IntPtr)(void*)null; else { ref pinnableReference = ref printerName.GetPinnableReference(); value = (IntPtr)(&pinnableReference); } string outputPort = GetOutputPort(); IntPtr intPtr; if (outputPort == null) intPtr = (IntPtr)(void*)null; else { ref pinnableReference2 = ref outputPort.GetPinnableReference(); intPtr = (IntPtr)(&pinnableReference2); } char* value2 = (char*)(long)intPtr; int num = PInvoke.DeviceCapabilities((char*)(long)value, value2, capability, (char*)output, null); if (num != -1) return num; return defaultValue; } private static string GetDefaultPrinterName() { return GetDefaultName(1); } private static string GetOutputPort() { return GetDefaultName(2); } private unsafe static string GetDefaultName(int slot) { PRINTDLGEXW pRINTDLGEXW = default(PRINTDLGEXW); pRINTDLGEXW.lStructSize = (uint)sizeof(PRINTDLGEXW); pRINTDLGEXW.Flags = (PRINTDLGEX_FLAGS.PD_NOPAGENUMS | PRINTDLGEX_FLAGS.PD_RETURNDEFAULT); pRINTDLGEXW.hwndOwner = PInvokeCore.GetDesktopWindow(); pRINTDLGEXW.nStartPage = uint.MaxValue; PRINTDLGEXW pRINTDLGEXW2 = pRINTDLGEXW; if (PInvokeCore.PrintDlgEx(&pRINTDLGEXW2).Failed) return System.SR.NoDefaultPrinter; HGLOBAL hDevNames = pRINTDLGEXW2.hDevNames; DEVNAMES* ptr = (DEVNAMES*)PInvokeCore.GlobalLock(hDevNames); if (ptr == null) throw new Win32Exception(); string text; switch (slot) { case 1: text = new string((char*)((byte*)ptr + (long)(int)ptr->wDeviceOffset * 2)); break; case 2: text = new string((char*)((byte*)ptr + (long)(int)ptr->wOutputOffset * 2)); break; default: throw new InvalidOperationException(); } string result = text; PInvokeCore.GlobalUnlock(hDevNames); PInvokeCore.GlobalFree(pRINTDLGEXW2.hDevNames); PInvokeCore.GlobalFree(pRINTDLGEXW2.hDevMode); return result; } private int GetDeviceCaps(GET_DEVICE_CAPS_INDEX capability) { CreateDcScope scope = CreateInformationContext(DefaultPageSettings); try { return PInvokeCore.GetDeviceCaps((HDC)ref scope, capability); } finally { scope.Dispose(); } } public IntPtr GetHdevmode() { HGLOBAL hdevmodeInternal = GetHdevmodeInternal(); _defaultPageSettings.CopyToHdevmode(hdevmodeInternal); return hdevmodeInternal; } internal unsafe HGLOBAL GetHdevmodeInternal() { string printerNameInternal = PrinterNameInternal; IntPtr intPtr; if (printerNameInternal == null) intPtr = (IntPtr)(void*)null; else { ref pinnableReference = ref printerNameInternal.GetPinnableReference(); intPtr = (IntPtr)(&pinnableReference); } char* printerName = (char*)(long)intPtr; return GetHdevmodeInternal(printerName); } [NullableContext(0)] private unsafe HGLOBAL GetHdevmodeInternal(char* printerName) { int num = -1; num = PInvoke.DocumentProperties(default(HWND), default(HANDLE), printerName, null, null, 0); if (num < 1) throw new InvalidPrinterException(this); HGLOBAL hGLOBAL = PInvokeCore.GlobalAlloc(GLOBAL_ALLOC_FLAGS.GMEM_MOVEABLE, (UIntPtr)(uint)num); DEVMODEW* ptr = (DEVMODEW*)PInvokeCore.GlobalLock(hGLOBAL); if (_cachedDevmode != null) Marshal.Copy(_cachedDevmode, 0, (IntPtr)ptr, _devmodeBytes); else { num = PInvoke.DocumentProperties(default(HWND), default(HANDLE), printerName, ptr, null, 2); if (num < 0) throw new Win32Exception(); } if (_extraInfo != null && _extraBytes <= ptr->dmDriverExtra) Marshal.Copy(_extraInfo, 0, (IntPtr)((byte*)ptr + (int)ptr->dmSize), _extraBytes); if (ptr->dmFields.HasFlag(DEVMODE_FIELD_FLAGS.DM_COPIES) && _copies != -1) ptr->Anonymous1.Anonymous1.dmCopies = _copies; if (ptr->dmFields.HasFlag(DEVMODE_FIELD_FLAGS.DM_DUPLEX) && _duplex != Duplex.Default) ptr->dmDuplex = (DEVMODE_DUPLEX)_duplex; if (ptr->dmFields.HasFlag(DEVMODE_FIELD_FLAGS.DM_COLLATE) && _collate.IsNotDefault) ptr->dmCollate = (_collate.IsTrue ? DEVMODE_COLLATE.DMCOLLATE_TRUE : DEVMODE_COLLATE.DMCOLLATE_FALSE); num = PInvoke.DocumentProperties(default(HWND), default(HANDLE), printerName, ptr, ptr, 10); if (num < 0) { PInvokeCore.GlobalFree(hGLOBAL); PInvokeCore.GlobalUnlock(hGLOBAL); return default(HGLOBAL); } PInvokeCore.GlobalUnlock(hGLOBAL); return hGLOBAL; } public IntPtr GetHdevmode(PageSettings pageSettings) { IntPtr intPtr = GetHdevmodeInternal(); pageSettings.CopyToHdevmode(intPtr); return intPtr; } public unsafe IntPtr GetHdevnames() { string printerName = PrinterName; string driverName = DriverName; string outputPort = OutputPort; int num = checked(4 + printerName.Length + driverName.Length + outputPort.Length); int num2 = sizeof(DEVNAMES) / 2; int num3 = checked(num2 + num); HGLOBAL hGLOBAL = PInvokeCore.GlobalAlloc(GLOBAL_ALLOC_FLAGS.GHND, (UIntPtr)(uint)(2 * num3)); DEVNAMES* ptr = (DEVNAMES*)PInvokeCore.GlobalLock(hGLOBAL); Span<char> span = new Span<char>(ptr, num3); ptr->wDriverOffset = checked((ushort)num2); ReadOnlySpan<char> readOnlySpan = driverName.AsSpan(); readOnlySpan.CopyTo(span.Slice(num2, driverName.Length)); num2 += (ushort)(driverName.Length + 1); ptr->wDeviceOffset = checked((ushort)num2); readOnlySpan = printerName.AsSpan(); readOnlySpan.CopyTo(span.Slice(num2, printerName.Length)); num2 += (ushort)(printerName.Length + 1); ptr->wOutputOffset = checked((ushort)num2); readOnlySpan = outputPort.AsSpan(); readOnlySpan.CopyTo(span.Slice(num2, outputPort.Length)); num2 += (ushort)(outputPort.Length + 1); ptr->wDefault = checked((ushort)num2); PInvokeCore.GlobalUnlock(hGLOBAL); return hGLOBAL; } internal short GetModeField(ModeField field, short defaultValue) { return GetModeField(field, defaultValue, default(HGLOBAL)); } internal unsafe short GetModeField(ModeField field, short defaultValue, HGLOBAL modeHandle) { bool flag = false; try { if ((long)(IntPtr)modeHandle == 0) try { modeHandle = GetHdevmodeInternal(); flag = true; } catch (InvalidPrinterException) { return defaultValue; } DEVMODEW* ptr = (DEVMODEW*)PInvokeCore.GlobalLock(modeHandle); short result; switch (field) { case ModeField.Orientation: result = ptr->dmOrientation; break; case ModeField.PaperSize: result = ptr->dmPaperSize; break; case ModeField.PaperLength: result = ptr->dmPaperLength; break; case ModeField.PaperWidth: result = ptr->dmPaperWidth; break; case ModeField.Copies: result = ptr->dmCopies; break; case ModeField.DefaultSource: result = ptr->dmDefaultSource; break; case ModeField.PrintQuality: result = ptr->dmPrintQuality; break; case ModeField.Color: result = (short)ptr->dmColor; break; case ModeField.Duplex: result = (short)ptr->dmDuplex; break; case ModeField.YResolution: result = ptr->dmYResolution; break; case ModeField.TTOption: result = (short)ptr->dmTTOption; break; case ModeField.Collate: result = (short)ptr->dmCollate; break; default: result = defaultValue; break; } PInvokeCore.GlobalUnlock(modeHandle); return result; } finally { if (flag) PInvokeCore.GlobalFree(modeHandle); } } internal unsafe PaperSize[] Get_PaperSizes() { string printerName = PrinterName; int num = FastDeviceCapabilities(PRINTER_DEVICE_CAPABILITIES.DC_PAPERNAMES, printerName, null, -1); if (num != -1) { int num2 = num; BufferScope<char> bufferScope = new BufferScope<char>(64 * num2); try { fixed (char* output = &bufferScope.GetPinnableReference()) { num = FastDeviceCapabilities(PRINTER_DEVICE_CAPABILITIES.DC_PAPERNAMES, printerName, output, -1); } int num3 = num2; Span<ushort> span = new Span<ushort>(stackalloc byte[(int)checked(unchecked((ulong)(uint)num3) * 2)], num3); fixed (ushort* output2 = &span.GetPinnableReference()) { num = FastDeviceCapabilities(PRINTER_DEVICE_CAPABILITIES.DC_PAPERS, printerName, output2, -1); } num3 = num2; Span<Size> span2 = new Span<Size>(stackalloc Size[num3], num3); fixed (Size* output3 = &span2.GetPinnableReference()) { num = FastDeviceCapabilities(PRINTER_DEVICE_CAPABILITIES.DC_PAPERSIZE, printerName, output3, -1); } PaperSize[] array = new PaperSize[num2]; for (int i = 0; i < num2; i++) { array[i] = new PaperSize((PaperKind)span[i], bufferScope.Slice(i * 64, 64).SliceAtFirstNull().ToString(), PrinterUnitConvert.Convert(span2[i].Width, PrinterUnit.TenthsOfAMillimeter, PrinterUnit.Display), PrinterUnitConvert.Convert(span2[i].Height, PrinterUnit.TenthsOfAMillimeter, PrinterUnit.Display)); } return array; } finally { bufferScope.Dispose(); } } return Array.Empty<PaperSize>(); } internal unsafe PaperSource[] Get_PaperSources() { string printerName = PrinterName; int num = FastDeviceCapabilities(PRINTER_DEVICE_CAPABILITIES.DC_BINNAMES, printerName, null, -1); if (num != -1) { int num2 = num; BufferScope<char> bufferScope = new BufferScope<char>(24 * num2); try { fixed (char* output = &bufferScope.GetPinnableReference()) { num = FastDeviceCapabilities(PRINTER_DEVICE_CAPABILITIES.DC_BINNAMES, printerName, output, -1); } int num3 = num2; Span<ushort> span = new Span<ushort>(stackalloc byte[(int)checked(unchecked((ulong)(uint)num3) * 2)], num3); fixed (ushort* output2 = &span.GetPinnableReference()) { FastDeviceCapabilities(PRINTER_DEVICE_CAPABILITIES.DC_BINS, printerName, output2, -1); } PaperSource[] array = new PaperSource[num2]; for (int i = 0; i < num2; i++) { array[i] = new PaperSource((PaperSourceKind)span[i], bufferScope.Slice(i * 24, 24).SliceAtFirstNull().ToString()); } return array; } finally { bufferScope.Dispose(); } } return Array.Empty<PaperSource>(); } internal unsafe PrinterResolution[] Get_PrinterResolutions() { string printerName = PrinterName; int num = FastDeviceCapabilities(PRINTER_DEVICE_CAPABILITIES.DC_ENUMRESOLUTIONS, printerName, null, -1); if (num == -1) return new PrinterResolution[4] { new PrinterResolution(PrinterResolutionKind.High, -4, -1), new PrinterResolution(PrinterResolutionKind.Medium, -3, -1), new PrinterResolution(PrinterResolutionKind.Low, -2, -1), new PrinterResolution(PrinterResolutionKind.Draft, -1, -1) }; PrinterResolution[] array = new PrinterResolution[num + 4]; array[0] = new PrinterResolution(PrinterResolutionKind.High, -4, -1); array[1] = new PrinterResolution(PrinterResolutionKind.Medium, -3, -1); array[2] = new PrinterResolution(PrinterResolutionKind.Low, -2, -1); array[3] = new PrinterResolution(PrinterResolutionKind.Draft, -1, -1); int num2 = num; Span<Point> span = new Span<Point>(stackalloc Point[num2], num2); fixed (Point* output = &span.GetPinnableReference()) { FastDeviceCapabilities(PRINTER_DEVICE_CAPABILITIES.DC_ENUMRESOLUTIONS, printerName, output, -1); } for (int i = 0; i < num; i++) { Point point = span[i]; array[i + 4] = new PrinterResolution(PrinterResolutionKind.Custom, point.X, point.Y); } return array; } public unsafe void SetHdevmode(IntPtr hdevmode) { if (hdevmode == (IntPtr)0) throw new ArgumentException(System.SR.Format(System.SR.InvalidPrinterHandle, hdevmode)); DEVMODEW* ptr = (DEVMODEW*)PInvokeCore.GlobalLock((HGLOBAL)hdevmode); _devmodeBytes = ptr->dmSize; if (_devmodeBytes > 0) { _cachedDevmode = new byte[_devmodeBytes]; Marshal.Copy((IntPtr)ptr, _cachedDevmode, 0, _devmodeBytes); } _extraBytes = ptr->dmDriverExtra; if (_extraBytes > 0) { _extraInfo = new byte[_extraBytes]; Marshal.Copy((IntPtr)((byte*)ptr + (int)ptr->dmSize), _extraInfo, 0, _extraBytes); } if (ptr->dmFields.HasFlag(DEVMODE_FIELD_FLAGS.DM_COPIES)) _copies = ptr->dmCopies; if (ptr->dmFields.HasFlag(DEVMODE_FIELD_FLAGS.DM_DUPLEX)) _duplex = (Duplex)ptr->dmDuplex; if (ptr->dmFields.HasFlag(DEVMODE_FIELD_FLAGS.DM_COLLATE)) _collate = (ptr->dmCollate == DEVMODE_COLLATE.DMCOLLATE_TRUE); PInvokeCore.GlobalUnlock((HGLOBAL)hdevmode); } public unsafe void SetHdevnames(IntPtr hdevnames) { if (hdevnames == (IntPtr)0) throw new ArgumentException(System.SR.Format(System.SR.InvalidPrinterHandle, hdevnames)); DEVNAMES* ptr = (DEVNAMES*)PInvokeCore.GlobalLock((HGLOBAL)hdevnames); _driverName = new string((char*)((byte*)ptr + (long)(int)ptr->wDriverOffset * 2)); _printerName = new string((char*)((byte*)ptr + (long)(int)ptr->wDeviceOffset * 2)); OutputPort = new string((char*)((byte*)ptr + (long)(int)ptr->wOutputOffset * 2)); PrintDialogDisplayed = true; PInvokeCore.GlobalUnlock((HGLOBAL)hdevnames); } public override string ToString() { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(104, 9); defaultInterpolatedStringHandler.AppendLiteral("[PrinterSettings "); defaultInterpolatedStringHandler.AppendFormatted(PrinterName); defaultInterpolatedStringHandler.AppendLiteral(" Copies="); defaultInterpolatedStringHandler.AppendFormatted(Copies); defaultInterpolatedStringHandler.AppendLiteral(" Collate="); defaultInterpolatedStringHandler.AppendFormatted(Collate); defaultInterpolatedStringHandler.AppendLiteral(" Duplex="); defaultInterpolatedStringHandler.AppendFormatted(Duplex); defaultInterpolatedStringHandler.AppendLiteral(" FromPage="); defaultInterpolatedStringHandler.AppendFormatted(FromPage); defaultInterpolatedStringHandler.AppendLiteral(" LandscapeAngle="); defaultInterpolatedStringHandler.AppendFormatted(LandscapeAngle); defaultInterpolatedStringHandler.AppendLiteral(" MaximumCopies="); defaultInterpolatedStringHandler.AppendFormatted(MaximumCopies); defaultInterpolatedStringHandler.AppendLiteral(" OutputPort="); defaultInterpolatedStringHandler.AppendFormatted(OutputPort); defaultInterpolatedStringHandler.AppendLiteral(" ToPage="); defaultInterpolatedStringHandler.AppendFormatted(ToPage); defaultInterpolatedStringHandler.AppendLiteral("]"); return defaultInterpolatedStringHandler.ToStringAndClear(); } } }