/// EditPrinterSettings #region EditPrinterSettings /// <summary> /// Shows Edit Printer Settings dialog /// </summary> /// <param name="printerSettings">printer settings</param> /// <param name="handle">dialog owner handle</param> /// <returns>dialog result</returns> public static DialogResult EditPrinterSettings(PrinterSettings printerSettings, IntPtr handle) { DialogResult myReturnValue = DialogResult.Cancel; // get handle to devmode IntPtr hDevMode = printerSettings.GetHdevmode(printerSettings.DefaultPageSettings); // lock data IntPtr pDevMode = GlobalLock(hDevMode); // get properties int sizeNeeded = DocumentProperties(handle, IntPtr.Zero, printerSettings.PrinterName, pDevMode, pDevMode, 0); IntPtr devModeData = Marshal.AllocHGlobal(sizeNeeded); // show dialog long userChoice = DocumentProperties(handle, IntPtr.Zero, printerSettings.PrinterName, devModeData, pDevMode, DM_IN_BUFFER | DM_PROMPT | DM_OUT_BUFFER); long IDOK = (long)DialogResult.OK; // set and save settings from dialog if (userChoice == IDOK) { myReturnValue = DialogResult.OK; printerSettings.SetHdevmode(devModeData); printerSettings.DefaultPageSettings.SetHdevmode(devModeData); } // unlock data and free memory GlobalUnlock(hDevMode); GlobalFree(hDevMode); Marshal.FreeHGlobal(devModeData); return(myReturnValue); }
/// <summary> /// Применение настроек принтера полученных из файла или из массива байт (mode=1 - загрузка из файла/ mode=2 - загрузка из переданного массива) /// </summary> /// <param name="printerSettings"></param> /// <param name="Filename"></param> /// /// <param name="Filename"></param> public void SetDevmode(PrinterSettings printerSettings, int mode, String Filename, byte[] devmodearray) //Grabs the data in arraylist and chucks it back into memory "Crank the suckers out" { ///int mode ///1 = Load devmode structure from file ///2 = Load devmode structure from arraylist IntPtr hDevMode = IntPtr.Zero; // a handle to our current DEVMODE IntPtr pDevMode = IntPtr.Zero; // a pointer to our current DEVMODE Byte[] Temparray; try { var DevModeArray = devmodearray; // Obtain the current DEVMODE position in memory hDevMode = printerSettings.GetHdevmode(printerSettings.DefaultPageSettings); // Obtain a lock on the handle and get an actual pointer so Windows won't move // it around while we're futzing with it pDevMode = GlobalLock(hDevMode); // Overwrite our current DEVMODE in memory with the one we saved. // They should be the same size since we haven't like upgraded the OS // or anything. if (mode == 1) //Load devmode structure from file { FileStream fs = new FileStream(Filename, FileMode.Open, FileAccess.Read); Temparray = new byte[fs.Length]; fs.Read(Temparray, 0, Temparray.Length); fs.Close(); fs.Dispose(); for (int i = 0; i < Temparray.Length; ++i) { Marshal.WriteByte(pDevMode, i, Temparray[i]); } } if (mode == 2) //Load devmode structure from arraylist { for (int i = 0; i < DevModeArray.Length; ++i) { Marshal.WriteByte(pDevMode, i, DevModeArray[i]); } } // We're done futzing GlobalUnlock(hDevMode); // Tell our printer settings to use the one we just overwrote printerSettings.SetHdevmode(hDevMode); printerSettings.DefaultPageSettings.SetHdevmode(hDevMode); // It's copied to our printer settings, so we can free the OS-level one GlobalFree(hDevMode); } catch (Exception ex) { if (hDevMode != IntPtr.Zero) { MessageBox.Show("BUGGER"); GlobalUnlock(hDevMode); // And to boot, we don't need that DEVMODE anymore, either GlobalFree(hDevMode); hDevMode = IntPtr.Zero; } } }
public static byte[] GetDevModeData(this PrinterSettings settings) { //Contract.Requires(settings != null); byte[] devModeData; RuntimeHelpers.PrepareConstrainedRegions(); try { // cer since hDevMode is not a SafeHandle } finally { var hDevMode = settings.GetHdevmode(); try { IntPtr pDevMode = NativeMethods.GlobalLock(hDevMode); try { var devMode = (NativeMethods.DEVMODE)Marshal.PtrToStructure( pDevMode, typeof(NativeMethods.DEVMODE)); var devModeSize = devMode.dmSize + devMode.dmDriverExtra; devModeData = new byte[devModeSize]; Marshal.Copy(pDevMode, devModeData, 0, devModeSize); } finally { NativeMethods.GlobalUnlock(hDevMode); } } finally { Marshal.FreeHGlobal(hDevMode); } } return(devModeData); }
public void GetHdevmode_ReturnsExpected() { var printerSettings = new PrinterSettings(); IntPtr handle = IntPtr.Zero; handle = printerSettings.GetHdevmode(); Assert.NotEqual(IntPtr.Zero, handle); }
private void OpenPrinterPropertiesDialog(PrinterSettings printerSettings) { IntPtr hDevMode = printerSettings.GetHdevmode(printerSettings.DefaultPageSettings); IntPtr pDevMode = GlobalLock(hDevMode); int sizeNeeded = DocumentProperties(this.Handle, IntPtr.Zero, printerSettings.PrinterName, pDevMode, ref pDevMode, 0); IntPtr devModeData = Marshal.AllocHGlobal(sizeNeeded); DocumentProperties(this.Handle, IntPtr.Zero, printerSettings.PrinterName, devModeData, ref pDevMode, 14); GlobalUnlock(hDevMode); printerSettings.SetHdevmode(devModeData); printerSettings.DefaultPageSettings.SetHdevmode(devModeData); GlobalFree(hDevMode); Marshal.FreeHGlobal(devModeData); }
private void OpenPrinterPropertiesDialog(PrinterSettings printerSettings) { var handle = (new System.Windows.Interop.WindowInteropHelper(this)).Handle; var hDevMode = printerSettings.GetHdevmode(printerSettings.DefaultPageSettings); var pDevMode = GlobalLock(hDevMode); var sizeNeeded = DocumentProperties(handle, IntPtr.Zero, printerSettings.PrinterName, pDevMode, ref pDevMode, 0); var devModeData = Marshal.AllocHGlobal(sizeNeeded); DocumentProperties(handle, IntPtr.Zero, printerSettings.PrinterName, devModeData, ref pDevMode, 14); GlobalUnlock(hDevMode); printerSettings.SetHdevmode(devModeData); printerSettings.DefaultPageSettings.SetHdevmode(devModeData); GlobalFree(hDevMode); Marshal.FreeHGlobal(devModeData); }
/* We have to do some calling into native methods to deal with and show * the advanced properties referenced by the DEVMODE struture. Ugly, * but I could not figure out how to do with direct WPF C# methods */ private void ShowProperties(object sender, RoutedEventArgs e) { try { /* First try to open the printer */ IntPtr phPrinter; int result = print_nativeapi.OpenPrinter(m_ps.PrinterName, out phPrinter, IntPtr.Zero); if (result == 0) { return; } /* Get a pointer to the DEVMODE */ IntPtr hDevMode = m_ps.GetHdevmode(m_ps.DefaultPageSettings); IntPtr pDevMode = print_nativeapi.GlobalLock(hDevMode); /* Native method wants a handle to our main window */ IntPtr hwin = new WindowInteropHelper(this).Handle; /* Get size of DEVMODE */ int sizeNeeded = print_nativeapi.DocumentProperties(hwin, IntPtr.Zero, m_ps.PrinterName, IntPtr.Zero, pDevMode, 0); /* Allocate */ IntPtr devModeData = Marshal.AllocHGlobal(sizeNeeded); /* Get devmode and show properties window */ print_nativeapi.DocumentProperties(hwin, IntPtr.Zero, m_ps.PrinterName, devModeData, pDevMode, fModes.DM_IN_PROMPT | fModes.DM_OUT_BUFFER); /* Set the properties, 9 = PRINTER_INFO_9. This was * tricky to figure out how to do */ PRINTER_INFO_9 info = new PRINTER_INFO_9(); info.pDevMode = devModeData; IntPtr infoPtr = Marshal.AllocHGlobal(Marshal.SizeOf <PRINTER_INFO_9>()); Marshal.StructureToPtr <PRINTER_INFO_9>(info, infoPtr, false); result = print_nativeapi.SetPrinter(phPrinter, 9, infoPtr, 0); /* Clean up */ print_nativeapi.GlobalUnlock(hDevMode); print_nativeapi.GlobalFree(hDevMode); Marshal.FreeHGlobal(infoPtr); //Marshal.FreeHGlobal(devModeData); /* NB: Freeing this causes bad things for some reason. */ } catch (Exception except) { main.ShowMessage(NotifyType_t.MESS_ERROR, "Exception in native print interface:" + except.Message); } }
public void SetHdevmode_IntPtr_Success() { var printerSettings = new PrinterSettings() { Copies = 3 }; var newPrinterSettings = new PrinterSettings() { Copies = 6 }; IntPtr handle = printerSettings.GetHdevmode(); newPrinterSettings.SetHdevmode(handle); Assert.Equal(printerSettings.Copies, newPrinterSettings.Copies); Assert.Equal(printerSettings.Collate, newPrinterSettings.Collate); Assert.Equal(printerSettings.Duplex, newPrinterSettings.Duplex); }
public static void ShowPropertiesDialog(PrinterSettings printerSettings) { IntPtr hDevMode = printerSettings.GetHdevmode(printerSettings.DefaultPageSettings); IntPtr handle; OpenPrinter(printerSettings.PrinterName, out handle, IntPtr.Zero); IntPtr pDevMode = GlobalLock(hDevMode); int result = DocumentProperties(IntPtr.Zero, handle, printerSettings.PrinterName, pDevMode, pDevMode, DM_IN_BUFFER | DM_PROMPT | DM_OUT_BUFFER); GlobalUnlock(hDevMode); if (result == 1) { printerSettings.SetHdevmode(hDevMode); printerSettings.DefaultPageSettings.SetHdevmode(hDevMode); } ClosePrinter(handle); }
public void SetHdevmode_IntPtr_Success() { string printerName = GetNameOfTestPrinterSuitableForDevModeTesting(); var printerSettings = new PrinterSettings() { PrinterName = printerName, Copies = 3 }; var newPrinterSettings = new PrinterSettings() { PrinterName = printerName, Copies = 6 }; IntPtr handle = printerSettings.GetHdevmode(); newPrinterSettings.SetHdevmode(handle); Assert.Equal(printerSettings.Copies, newPrinterSettings.Copies); Assert.Equal(printerSettings.Collate, newPrinterSettings.Collate); Assert.Equal(printerSettings.Duplex, newPrinterSettings.Duplex); }
public static void OpenPrinterPropertiesDialog(PrinterSettings printerSettings, IntPtr handle) { IntPtr hDevMode = printerSettings.GetHdevmode(printerSettings.DefaultPageSettings); IntPtr pDevMode = GlobalLock(hDevMode); int sizeNeeded = DocumentProperties(handle, IntPtr.Zero, printerSettings.PrinterName, IntPtr.Zero, pDevMode, 0); if (sizeNeeded < 0) { GlobalUnlock(hDevMode); return; } IntPtr devModeData = Marshal.AllocHGlobal(sizeNeeded); DocumentProperties(handle, IntPtr.Zero, printerSettings.PrinterName, devModeData, pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER | DM_PROMPT); GlobalUnlock(hDevMode); printerSettings.SetHdevmode(devModeData); printerSettings.DefaultPageSettings.SetHdevmode(devModeData); GlobalFree(hDevMode); Marshal.FreeHGlobal(devModeData); }
private DialogResult EditPrinterSettings(PrinterSettings printerSettings) { DialogResult myReturnValue = DialogResult.Cancel; IntPtr hDevMode = printerSettings.GetHdevmode(printerSettings.DefaultPageSettings); IntPtr pDevMode = GlobalLock(hDevMode); int sizeNeeded = DocumentProperties(this.Handle, IntPtr.Zero, printerSettings.PrinterName, IntPtr.Zero, pDevMode, 0); IntPtr devModeData = Marshal.AllocHGlobal(sizeNeeded); long userChoice = DocumentProperties(this.Handle, IntPtr.Zero, printerSettings.PrinterName, devModeData, pDevMode, DM_IN_BUFFER | DM_PROMPT | DM_OUT_BUFFER); long IDOK = (long)DialogResult.OK; if (userChoice == IDOK) { myReturnValue = DialogResult.OK; printerSettings.SetHdevmode(devModeData); printerSettings.DefaultPageSettings.SetHdevmode(devModeData); } GlobalUnlock(hDevMode); GlobalFree(hDevMode); Marshal.FreeHGlobal(devModeData); return(myReturnValue); }
} // proc SetPrintTicket /// <summary>Copy printer settings from System.Drawing to System.Printing</summary> /// <param name="printerSettings"></param> /// <param name="printQueue"></param> /// <param name="printTicket"></param> public static unsafe void SetPrinterSettings(this PrinterSettings printerSettings, out PrintQueue printQueue, out PrintTicket printTicket) { using (var printTicketConverter = new PrintTicketConverter(printerSettings.PrinterName, PrintTicketConverter.MaxPrintSchemaVersion)) using (var printServer = new LocalPrintServer()) { printQueue = printServer.GetPrintQueue(printerSettings.PrinterName); var hDevMode = printerSettings.GetHdevmode(); try { var pDevMode = NativeMethods.GlobalLock(hDevMode); var bDevMode = new byte[NativeMethods.GlobalSize(hDevMode).ToInt32()]; Marshal.Copy(pDevMode, bDevMode, 0, bDevMode.Length); NativeMethods.GlobalUnlock(hDevMode); printTicket = printTicketConverter.ConvertDevModeToPrintTicket(bDevMode, PrintTicketScope.JobScope); } finally { Marshal.FreeHGlobal(hDevMode); } } } // proc SetPrinterSettings
private bool ShowPrintDialog(IntPtr hwndOwner, NativeMethods.WndProc hookProcPtr, NativeMethods.PRINTDLG data) { data.Flags = GetFlags(); data.nCopies = (short)PrinterSettings.Copies; data.hwndOwner = hwndOwner; data.lpfnPrintHook = hookProcPtr; try { if (PageSettings == null) { data.hDevMode = PrinterSettings.GetHdevmode(); } else { data.hDevMode = PrinterSettings.GetHdevmode(PageSettings); } data.hDevNames = PrinterSettings.GetHdevnames(); } catch (InvalidPrinterException) { data.hDevMode = IntPtr.Zero; data.hDevNames = IntPtr.Zero; // Leave those fields null; Windows will fill them in } try { // Windows doesn't like it if page numbers are invalid if (AllowSomePages) { if (PrinterSettings.FromPage < PrinterSettings.MinimumPage || PrinterSettings.FromPage > PrinterSettings.MaximumPage) { throw new ArgumentException(string.Format(SR.PDpageOutOfRange, "FromPage")); } if (PrinterSettings.ToPage < PrinterSettings.MinimumPage || PrinterSettings.ToPage > PrinterSettings.MaximumPage) { throw new ArgumentException(string.Format(SR.PDpageOutOfRange, "ToPage")); } if (PrinterSettings.ToPage < PrinterSettings.FromPage) { throw new ArgumentException(string.Format(SR.PDpageOutOfRange, "FromPage")); } data.nFromPage = (short)PrinterSettings.FromPage; data.nToPage = (short)PrinterSettings.ToPage; data.nMinPage = (short)PrinterSettings.MinimumPage; data.nMaxPage = (short)PrinterSettings.MaximumPage; } if (!UnsafeNativeMethods.PrintDlg(data)) { return(false); } UpdatePrinterSettings(data.hDevMode, data.hDevNames, data.nCopies, data.Flags, settings, PageSettings); PrintToFile = ((data.Flags & NativeMethods.PD_PRINTTOFILE) != 0); PrinterSettings.PrintToFile = PrintToFile; if (AllowSomePages) { PrinterSettings.FromPage = data.nFromPage; PrinterSettings.ToPage = data.nToPage; } // When the flag PD_USEDEVMODECOPIESANDCOLLATE is not set, // PRINTDLG.nCopies or PRINTDLG.nCopies indicates the number of copies the user wants // to print, and the PD_COLLATE flag in the Flags member indicates // whether the user wants to print them collated. if ((data.Flags & NativeMethods.PD_USEDEVMODECOPIESANDCOLLATE) == 0) { PrinterSettings.Copies = data.nCopies; PrinterSettings.Collate = ((data.Flags & NativeMethods.PD_COLLATE) == NativeMethods.PD_COLLATE); } return(true); } finally { UnsafeNativeMethods.GlobalFree(new HandleRef(data, data.hDevMode)); UnsafeNativeMethods.GlobalFree(new HandleRef(data, data.hDevNames)); } }
public void GetHdevmode_Null_ThrowsNullReferenceException() { var printerSettings = new PrinterSettings(); Assert.Throws <NullReferenceException>(() => printerSettings.GetHdevmode(null)); }
/// <include file='doc\PrintDialog.uex' path='docs/doc[@for="PrintDialog.RunDialog"]/*' /> /// <devdoc> /// </devdoc> /// <internalonly/> protected override bool RunDialog(IntPtr hwndOwner) { IntSecurity.SafePrinting.Demand(); NativeMethods.WndProc hookProcPtr = new NativeMethods.WndProc(this.HookProc); if (settings == null) { throw new ArgumentException(SR.GetString(SR.PDcantShowWithoutPrinter)); } NativeMethods.PRINTDLG data = CreatePRINTDLG(); data.Flags = GetFlags(); data.nCopies = (short)settings.Copies; data.hwndOwner = hwndOwner; data.lpfnPrintHook = hookProcPtr; IntSecurity.AllPrinting.Assert(); try { if (PageSettings == null) { data.hDevMode = settings.GetHdevmode(); } else { data.hDevMode = settings.GetHdevmode(PageSettings); } data.hDevNames = settings.GetHdevnames(); } catch (InvalidPrinterException) { data.hDevMode = IntPtr.Zero; data.hDevNames = IntPtr.Zero; // Leave those fields null; Windows will fill them in } finally { CodeAccessPermission.RevertAssert(); } try { // Windows doesn't like it if page numbers are invalid if (AllowSomePages) { if (settings.FromPage < settings.MinimumPage || settings.FromPage > settings.MaximumPage) { throw new ArgumentException(SR.GetString(SR.PDpageOutOfRange, "FromPage")); } if (settings.ToPage < settings.MinimumPage || settings.ToPage > settings.MaximumPage) { throw new ArgumentException(SR.GetString(SR.PDpageOutOfRange, "ToPage")); } if (settings.ToPage < settings.FromPage) { throw new ArgumentException(SR.GetString(SR.PDpageOutOfRange, "FromPage")); } data.nFromPage = (short)settings.FromPage; data.nToPage = (short)settings.ToPage; data.nMinPage = (short)settings.MinimumPage; data.nMaxPage = (short)settings.MaximumPage; } if (!UnsafeNativeMethods.PrintDlg(data)) { return(false); } UpdatePrinterSettings(data, settings, PageSettings); PrintToFile = ((data.Flags & NativeMethods.PD_PRINTTOFILE) != 0); settings.PrintToFile = PrintToFile; if (AllowSomePages) { settings.FromPage = data.nFromPage; settings.ToPage = data.nToPage; } return(true); } finally { UnsafeNativeMethods.GlobalFree(new HandleRef(data, data.hDevMode)); UnsafeNativeMethods.GlobalFree(new HandleRef(data, data.hDevNames)); } }
/// <include file='doc\PageSetupDialog.uex' path='docs/doc[@for="PageSetupDialog.RunDialog"]/*' /> /// <devdoc> /// </devdoc> /// <internalonly/> protected override bool RunDialog(IntPtr hwndOwner) { IntSecurity.SafePrinting.Demand(); NativeMethods.WndProc hookProcPtr = new NativeMethods.WndProc(this.HookProc); if (pageSettings == null) { throw new ArgumentException(SR.GetString(SR.PSDcantShowWithoutPage)); } NativeMethods.PAGESETUPDLG data = new NativeMethods.PAGESETUPDLG(); data.lStructSize = Marshal.SizeOf(data); data.Flags = GetFlags(); data.hwndOwner = hwndOwner; data.lpfnPageSetupHook = hookProcPtr; if (MinMargins != null) { PrinterUnit toUnit = PrinterUnit.ThousandthsOfAnInch; Margins margins = PrinterUnitConvert.Convert(MinMargins, PrinterUnit.Display, toUnit); data.minMarginLeft = margins.Left; data.minMarginTop = margins.Top; data.minMarginRight = margins.Right; data.minMarginBottom = margins.Bottom; } if (pageSettings.Margins != null) { PrinterUnit toUnit = PrinterUnit.ThousandthsOfAnInch; Margins margins = PrinterUnitConvert.Convert(pageSettings.Margins, PrinterUnit.Display, toUnit); data.marginLeft = margins.Left; data.marginTop = margins.Top; data.marginRight = margins.Right; data.marginBottom = margins.Bottom; } // Ensure that the margins are >= minMargins. // This is a requirement of the PAGESETUPDLG structure. // data.marginLeft = Math.Max(data.marginLeft, data.minMarginLeft); data.marginTop = Math.Max(data.marginTop, data.minMarginTop); data.marginRight = Math.Max(data.marginRight, data.minMarginRight); data.marginBottom = Math.Max(data.marginBottom, data.minMarginBottom); PrinterSettings printer = (printerSettings == null) ? pageSettings.PrinterSettings : printerSettings; IntSecurity.AllPrinting.Assert(); try { data.hDevMode = printer.GetHdevmode(pageSettings); data.hDevNames = printer.GetHdevnames(); } finally { CodeAccessPermission.RevertAssert(); } try { bool status = UnsafeNativeMethods.PageSetupDlg(data); if (!status) { // Debug.WriteLine(Windows.CommonDialogErrorToString(Windows.CommDlgExtendedError())); return(false); } UpdateSettings(data, pageSettings, printerSettings); // yes, printerSettings, not printer return(true); } finally { UnsafeNativeMethods.GlobalFree(new HandleRef(data, data.hDevMode)); UnsafeNativeMethods.GlobalFree(new HandleRef(data, data.hDevNames)); } }
// VSWhidbey 93449: Due to the nature of PRINTDLGEX vs PRINTDLG, separate but similar methods // are required for showing the print dialog on Win2k and newer OS'. private bool ShowPrintDialog(IntPtr hwndOwner, NativeMethods.WndProc hookProcPtr, NativeMethods.PRINTDLG data) { data.Flags = GetFlags(); data.nCopies = (short)PrinterSettings.Copies; data.hwndOwner = hwndOwner; data.lpfnPrintHook = hookProcPtr; IntSecurity.AllPrintingAndUnmanagedCode.Assert(); try { if (PageSettings == null) { data.hDevMode = PrinterSettings.GetHdevmode(); } else { data.hDevMode = PrinterSettings.GetHdevmode(PageSettings); } data.hDevNames = PrinterSettings.GetHdevnames(); } catch (InvalidPrinterException) { data.hDevMode = IntPtr.Zero; data.hDevNames = IntPtr.Zero; // Leave those fields null; Windows will fill them in } finally { CodeAccessPermission.RevertAssert(); } try { // Windows doesn't like it if page numbers are invalid if (AllowSomePages) { if (PrinterSettings.FromPage < PrinterSettings.MinimumPage || PrinterSettings.FromPage > PrinterSettings.MaximumPage) { throw new ArgumentException(SR.GetString(SR.PDpageOutOfRange, "FromPage")); } if (PrinterSettings.ToPage < PrinterSettings.MinimumPage || PrinterSettings.ToPage > PrinterSettings.MaximumPage) { throw new ArgumentException(SR.GetString(SR.PDpageOutOfRange, "ToPage")); } if (PrinterSettings.ToPage < PrinterSettings.FromPage) { throw new ArgumentException(SR.GetString(SR.PDpageOutOfRange, "FromPage")); } data.nFromPage = (short)PrinterSettings.FromPage; data.nToPage = (short)PrinterSettings.ToPage; data.nMinPage = (short)PrinterSettings.MinimumPage; data.nMaxPage = (short)PrinterSettings.MaximumPage; } if (!UnsafeNativeMethods.PrintDlg(data)) { return(false); } IntSecurity.AllPrintingAndUnmanagedCode.Assert(); try { UpdatePrinterSettings(data.hDevMode, data.hDevNames, data.nCopies, data.Flags, settings, PageSettings); } finally { CodeAccessPermission.RevertAssert(); } PrintToFile = ((data.Flags & NativeMethods.PD_PRINTTOFILE) != 0); PrinterSettings.PrintToFile = PrintToFile; if (AllowSomePages) { PrinterSettings.FromPage = data.nFromPage; PrinterSettings.ToPage = data.nToPage; } // Fix Dev10 #575399, when the flag PD_USEDEVMODECOPIESANDCOLLATE is not set, // PRINTDLG.nCopies or PRINTDLG.nCopies indicates the number of copies the user wants // to print, and the PD_COLLATE flag in the Flags member indicates // whether the user wants to print them collated. // Due to a Windows OS Bug 558734, we don't need to consider Windows XP and before if ((data.Flags & NativeMethods.PD_USEDEVMODECOPIESANDCOLLATE) == 0) { if (Environment.OSVersion.Version.Major >= 6) { PrinterSettings.Copies = data.nCopies; PrinterSettings.Collate = ((data.Flags & NativeMethods.PD_COLLATE) == NativeMethods.PD_COLLATE); } } return(true); } finally { UnsafeNativeMethods.GlobalFree(new HandleRef(data, data.hDevMode)); UnsafeNativeMethods.GlobalFree(new HandleRef(data, data.hDevNames)); } }
/// <summary> /// Сохранение в файл или в массив байт (mode = 1 - в файл/ mode=2 - в массив) /// </summary> /// <param name="printerSettings"></param> /// <param name="mode"></param> /// <param name="Filename"></param> public byte[] SaveDevmode(PrinterSettings printerSettings, int mode, String Filename) //Grabs the devmode data in memory and stores in arraylist { ///int mode ///1 = Save devmode structure to file ///2 = Save devmode structure to Byte array and arraylist IntPtr hDevMode = IntPtr.Zero; // handle to the DEVMODE IntPtr pDevMode = IntPtr.Zero; // pointer to the DEVMODE IntPtr hwnd = ((Form)_controller).Handle; byte[] DevModeArray = null; try { // Get a handle to a DEVMODE for the default printer settings hDevMode = printerSettings.GetHdevmode(printerSettings.DefaultPageSettings); // Obtain a lock on the handle and get an actual pointer so Windows won't // move it around while we're futzing with it pDevMode = GlobalLock(hDevMode); int sizeNeeded = DocumentProperties(hwnd, IntPtr.Zero, printerSettings.PrinterName, IntPtr.Zero, pDevMode, 0); if (sizeNeeded <= 0) { MessageBox.Show("Devmode Bummer, Cant get size of devmode structure"); GlobalUnlock(hDevMode); GlobalFree(hDevMode); return(null); } DevModeArray = new byte[sizeNeeded]; //Copies the buffer into a byte array if (mode == 1) //Save devmode structure to file { FileStream fs = new FileStream(Filename, FileMode.Create); for (int i = 0; i < sizeNeeded; ++i) { fs.WriteByte(Marshal.ReadByte(pDevMode, i)); } fs.Close(); fs.Dispose(); } if (mode == 2) //Save devmode structure to Byte array and arraylist { for (int i = 0; i < sizeNeeded; ++i) { DevModeArray[i] = (byte)(Marshal.ReadByte(pDevMode, i)); //Copies the array to an arraylist where it can be recalled } } // Unlock the handle, we're done futzing around with memory GlobalUnlock(hDevMode); // And to boot, we don't need that DEVMODE anymore, either GlobalFree(hDevMode); hDevMode = IntPtr.Zero; } catch (Exception ex) { if (hDevMode != IntPtr.Zero) { MessageBox.Show("BUGGER"); GlobalUnlock(hDevMode); // And to boot, we don't need that DEVMODE anymore, either GlobalFree(hDevMode); hDevMode = IntPtr.Zero; } } return(DevModeArray); }
private unsafe bool ShowPrintDialog(IntPtr hwndOwner) { PRINTDLGW data; if (IntPtr.Size == 4) { data = new PRINTDLGW_32 { lStructSize = (uint)sizeof(PRINTDLGW_32) }; } else { data = new PRINTDLGW_64 { lStructSize = (uint)sizeof(PRINTDLGW_64) }; } data.nFromPage = 1; data.nToPage = 1; data.nMinPage = 0; data.nMaxPage = 9999; data.Flags = GetFlags(); data.nCopies = (ushort)PrinterSettings.Copies; data.hwndOwner = hwndOwner; User32.WNDPROCINT wndproc = new User32.WNDPROCINT(HookProc); data.lpfnPrintHook = Marshal.GetFunctionPointerForDelegate(wndproc); try { if (PageSettings is null) { data.hDevMode = PrinterSettings.GetHdevmode(); } else { data.hDevMode = PrinterSettings.GetHdevmode(PageSettings); } data.hDevNames = PrinterSettings.GetHdevnames(); } catch (InvalidPrinterException) { // Leave those fields null; Windows will fill them in data.hDevMode = IntPtr.Zero; data.hDevNames = IntPtr.Zero; } try { // Windows doesn't like it if page numbers are invalid if (AllowSomePages) { if (PrinterSettings.FromPage < PrinterSettings.MinimumPage || PrinterSettings.FromPage > PrinterSettings.MaximumPage) { throw new ArgumentException(string.Format(SR.PDpageOutOfRange, "FromPage")); } if (PrinterSettings.ToPage < PrinterSettings.MinimumPage || PrinterSettings.ToPage > PrinterSettings.MaximumPage) { throw new ArgumentException(string.Format(SR.PDpageOutOfRange, "ToPage")); } if (PrinterSettings.ToPage < PrinterSettings.FromPage) { throw new ArgumentException(string.Format(SR.PDpageOutOfRange, "FromPage")); } data.nFromPage = (ushort)PrinterSettings.FromPage; data.nToPage = (ushort)PrinterSettings.ToPage; data.nMinPage = (ushort)PrinterSettings.MinimumPage; data.nMaxPage = (ushort)PrinterSettings.MaximumPage; } if (PrintDlg(ref data).IsFalse()) { var result = CommDlgExtendedError(); return(false); } UpdatePrinterSettings(data.hDevMode, data.hDevNames, (short)data.nCopies, data.Flags, settings, PageSettings); PrintToFile = (data.Flags & PD.PRINTTOFILE) != 0; PrinterSettings.PrintToFile = PrintToFile; if (AllowSomePages) { PrinterSettings.FromPage = data.nFromPage; PrinterSettings.ToPage = data.nToPage; } // When the flag PD_USEDEVMODECOPIESANDCOLLATE is not set, // PRINTDLG.nCopies or PRINTDLG.nCopies indicates the number of copies the user wants // to print, and the PD_COLLATE flag in the Flags member indicates // whether the user wants to print them collated. if ((data.Flags & PD.USEDEVMODECOPIESANDCOLLATE) == 0) { PrinterSettings.Copies = (short)data.nCopies; PrinterSettings.Collate = (data.Flags & PD.COLLATE) == PD.COLLATE; } return(true); } finally { GC.KeepAlive(wndproc); Kernel32.GlobalFree(data.hDevMode); Kernel32.GlobalFree(data.hDevNames); } }
// Due to the nature of PRINTDLGEX vs PRINTDLG, separate but similar methods // are required for showing the print dialog on Win2k and newer OS'. private bool ShowPrintDialog(IntPtr hwndOwner, NativeMethods.PRINTDLGEX data) { data.Flags = GetFlags(); data.nCopies = PrinterSettings.Copies; data.hwndOwner = hwndOwner; try { if (PageSettings == null) { data.hDevMode = PrinterSettings.GetHdevmode(); } else { data.hDevMode = PrinterSettings.GetHdevmode(PageSettings); } data.hDevNames = PrinterSettings.GetHdevnames(); } catch (InvalidPrinterException) { data.hDevMode = IntPtr.Zero; data.hDevNames = IntPtr.Zero; // Leave those fields null; Windows will fill them in } try { // Windows doesn't like it if page numbers are invalid if (AllowSomePages) { if (PrinterSettings.FromPage < PrinterSettings.MinimumPage || PrinterSettings.FromPage > PrinterSettings.MaximumPage) { throw new ArgumentException(string.Format(SR.PDpageOutOfRange, "FromPage")); } if (PrinterSettings.ToPage < PrinterSettings.MinimumPage || PrinterSettings.ToPage > PrinterSettings.MaximumPage) { throw new ArgumentException(string.Format(SR.PDpageOutOfRange, "ToPage")); } if (PrinterSettings.ToPage < PrinterSettings.FromPage) { throw new ArgumentException(string.Format(SR.PDpageOutOfRange, "FromPage")); } unsafe { int *pageRangeField = (int *)data.pageRanges; * pageRangeField = PrinterSettings.FromPage; pageRangeField += 1; *pageRangeField = PrinterSettings.ToPage; } data.nPageRanges = 1; data.nMinPage = PrinterSettings.MinimumPage; data.nMaxPage = PrinterSettings.MaximumPage; } // // The flags NativeMethods.PD_SHOWHELP and NativeMethods.PD_NONETWORKBUTTON don't work with // PrintDlgEx. So we have to strip them out. data.Flags &= ~(NativeMethods.PD_SHOWHELP | NativeMethods.PD_NONETWORKBUTTON); int hr = UnsafeNativeMethods.PrintDlgEx(data); if (NativeMethods.Failed(hr) || data.dwResultAction == NativeMethods.PD_RESULT_CANCEL) { return(false); } UpdatePrinterSettings(data.hDevMode, data.hDevNames, (short)data.nCopies, data.Flags, PrinterSettings, PageSettings); PrintToFile = ((data.Flags & NativeMethods.PD_PRINTTOFILE) != 0); PrinterSettings.PrintToFile = PrintToFile; if (AllowSomePages) { unsafe { int *pageRangeField = (int *)data.pageRanges; PrinterSettings.FromPage = *pageRangeField; pageRangeField += 1; PrinterSettings.ToPage = *pageRangeField; } } // When the flag PD_USEDEVMODECOPIESANDCOLLATE is not set, // PRINTDLG.nCopies or PRINTDLG.nCopies indicates the number of copies the user wants // to print, and the PD_COLLATE flag in the Flags member indicates // whether the user wants to print them collated. if ((data.Flags & NativeMethods.PD_USEDEVMODECOPIESANDCOLLATE) == 0) { PrinterSettings.Copies = (short)(data.nCopies); PrinterSettings.Collate = ((data.Flags & NativeMethods.PD_COLLATE) == NativeMethods.PD_COLLATE); } // We should return true only if the user pressed the "Print" button while dismissing the dialog. return(data.dwResultAction == NativeMethods.PD_RESULT_PRINT); } finally { if (data.hDevMode != IntPtr.Zero) { UnsafeNativeMethods.GlobalFree(new HandleRef(data, data.hDevMode)); } if (data.hDevNames != IntPtr.Zero) { UnsafeNativeMethods.GlobalFree(new HandleRef(data, data.hDevNames)); } if (data.pageRanges != IntPtr.Zero) { UnsafeNativeMethods.GlobalFree(new HandleRef(data, data.pageRanges)); } } }
protected override bool RunDialog(IntPtr hwndOwner) { NativeMethods.WndProc hookProcPtr = new NativeMethods.WndProc(HookProc); if (pageSettings == null) { throw new ArgumentException(SR.PSDcantShowWithoutPage); } NativeMethods.PAGESETUPDLG data = new NativeMethods.PAGESETUPDLG(); data.lStructSize = Marshal.SizeOf(data); data.Flags = GetFlags(); data.hwndOwner = hwndOwner; data.lpfnPageSetupHook = hookProcPtr; PrinterUnit toUnit = PrinterUnit.ThousandthsOfAnInch; // Below was a breaking change from RTM and EVERETT even though this was a correct FIX. // EnableMetric is a new Whidbey property which we allow the users to choose between the AutoConversion or not. if (EnableMetric) { //take the Units of Measurement while determining the PrinterUnits... // StringBuilder sb = new StringBuilder(2); int result = UnsafeNativeMethods.GetLocaleInfo(NativeMethods.LOCALE_USER_DEFAULT, NativeMethods.LOCALE_IMEASURE, sb, sb.Capacity); if (result > 0 && int.Parse(sb.ToString(), CultureInfo.InvariantCulture) == 0) { toUnit = PrinterUnit.HundredthsOfAMillimeter; } } if (MinMargins != null) { Margins margins = PrinterUnitConvert.Convert(MinMargins, PrinterUnit.Display, toUnit); data.minMarginLeft = margins.Left; data.minMarginTop = margins.Top; data.minMarginRight = margins.Right; data.minMarginBottom = margins.Bottom; } if (pageSettings.Margins != null) { Margins margins = PrinterUnitConvert.Convert(pageSettings.Margins, PrinterUnit.Display, toUnit); data.marginLeft = margins.Left; data.marginTop = margins.Top; data.marginRight = margins.Right; data.marginBottom = margins.Bottom; } // Ensure that the margins are >= minMargins. // This is a requirement of the PAGESETUPDLG structure. // data.marginLeft = Math.Max(data.marginLeft, data.minMarginLeft); data.marginTop = Math.Max(data.marginTop, data.minMarginTop); data.marginRight = Math.Max(data.marginRight, data.minMarginRight); data.marginBottom = Math.Max(data.marginBottom, data.minMarginBottom); PrinterSettings printer = printerSettings ?? pageSettings.PrinterSettings; data.hDevMode = printer.GetHdevmode(pageSettings); data.hDevNames = printer.GetHdevnames(); try { bool status = UnsafeNativeMethods.PageSetupDlg(data); if (!status) { // Debug.WriteLine(Windows.CommonDialogErrorToString(Windows.CommDlgExtendedError())); return(false); } UpdateSettings(data, pageSettings, printerSettings); // yes, printerSettings, not printer return(true); } finally { UnsafeNativeMethods.GlobalFree(new HandleRef(data, data.hDevMode)); UnsafeNativeMethods.GlobalFree(new HandleRef(data, data.hDevNames)); } }
// NOTE: this code is taken from C1Report printing. /// <summary> /// Creates a PrintDocument based on passed printer settings and current page settings. /// </summary> /// <param name="printerSettings">The printer settings to use. Must not be null.</param> /// <returns>An instance of PrintDocument that has the specified printer and page settings.</returns> /// <remarks> /// The code in this method tries to work around an issue with the standard page setup dialog: /// if the target printer supports papers that are absent from the System.Drawing.Printing.PaperKind /// enum, and such a paper is selected - in certain use scenarios the integrity of the printer and /// page settings is broken by the dialog, and on subsequent calls the dialog shows only the /// default paper. The key to avoiding this seems to be to use a PrintDocument, and to /// set the printer settings with Sethdevnames/Sethdevmode calls, and then to individually /// set the relevant page settings. TFS~~17823. /// </remarks> private PrintDocument _makePageSettingsPrintDocument(PageSettings pageSettings, PrinterSettings printerSettings) { var pdoc = new PrintDocument(); // Set printer settings: pdoc.PrinterSettings.SetHdevnames(printerSettings.GetHdevnames()); pdoc.PrinterSettings.SetHdevmode(printerSettings.GetHdevmode()); // Set relevant page settings (code is copied from C1PageSettings.ToPageSettings): var page = pageSettings; // cache page settings as they are created on the fly // color: pdoc.DefaultPageSettings.Color = page.Color; // orientation: pdoc.DefaultPageSettings.Landscape = page.Landscape; // margins: pdoc.DefaultPageSettings.Margins.Left = page.Margins.Left; pdoc.DefaultPageSettings.Margins.Right = page.Margins.Right; pdoc.DefaultPageSettings.Margins.Top = page.Margins.Top; pdoc.DefaultPageSettings.Margins.Bottom = page.Margins.Bottom; // paper source: PaperSource ps = null; if (page.PaperSource.Kind == PaperSourceKind.Custom) { foreach (PaperSource paperSource in pdoc.PrinterSettings.PaperSources) { if (paperSource.Kind == PaperSourceKind.Custom && paperSource.RawKind == page.PaperSource.RawKind) { ps = paperSource; break; } } } else { foreach (PaperSource paperSource in pdoc.PrinterSettings.PaperSources) { if (paperSource.Kind == page.PaperSource.Kind) { ps = paperSource; break; } } } if (ps == null) { ps = new PaperSource(); ps.SourceName = page.PaperSource.SourceName; ps.RawKind = page.PaperSource.RawKind; } pdoc.DefaultPageSettings.PaperSource = ps; // printer resolution: if (page.PrinterResolution != null && page.PrinterResolution.Kind == System.Drawing.Printing.PrinterResolutionKind.Custom) { PrinterResolution pr = new PrinterResolution(); pr.Kind = page.PrinterResolution.Kind; pr.X = page.PrinterResolution.X; pr.Y = page.PrinterResolution.Y; pdoc.DefaultPageSettings.PrinterResolution = pr; } else { foreach (PrinterResolution printerResolution in pdoc.PrinterSettings.PrinterResolutions) { if (printerResolution.Kind == page.PrinterResolution.Kind) { pdoc.DefaultPageSettings.PrinterResolution = printerResolution; break; } } } // paper size: assigning .NET PaperSize to a size where Kind is one missing from the PaperKind enum // (e.g. A0) causes the PageSetupDialog to break the associated devmode's integrity for subsequent calls, // so we don't mess with such papers at all: if (page.PaperSize.Kind != PaperKind.Custom) { foreach (PaperSize psize in pdoc.PrinterSettings.PaperSizes) { if (psize.Kind == page.PaperSize.Kind && pdoc.DefaultPageSettings.PaperSize.Kind != page.PaperSize.Kind) { pdoc.DefaultPageSettings.PaperSize = page.PaperSize; break; } } } return(pdoc); }