EDITOR: My fault! I expected the changes to revert to the default printer settings if only the local instance of PrinterSettings was actually changed. - The code below works as expected
I am trying to show custom printer properties for this printer. I need this as part of the custom PrintDialog I'm trying to write.
Most of the examples that I can find on the Internet can display a dialog box, but any changes that the user can make are lost, which makes it useless.
Example: http://www.codeproject.com/KB/system/PrinterPropertiesWindow.aspx
(regarding the above page: I tried to change the code as suggested by BartJoy (on the page), but this did not fix it)
I also tried the sample and suggestions on the pinvoke.net page, but it still doesn't work:
http://www.pinvoke.net/default.aspx/winspool.documentproperties
From the above websites, I assume that the problem can only be on 64-bit Windows and / or if the printer name is longer than 32 characters.
I do not know what I should try next ... I appreciate any suggestions and comments!
EDIT: Here is what I tried:
[DllImport("winspool.Drv", EntryPoint = "DocumentPropertiesW", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] static extern int DocumentProperties(IntPtr hwnd, IntPtr hPrinter, [MarshalAs(UnmanagedType.LPWStr)] string pDeviceName, IntPtr pDevModeOutput, IntPtr pDevModeInput, int fMode); [DllImport("winspool.drv")] private static extern int OpenPrinter(string pPrinterName, out IntPtr hPrinter, IntPtr pDefault); [DllImport("winspool.drv")] private static extern int ClosePrinter(IntPtr phPrinter); [DllImport("kernel32.dll")] static extern IntPtr GlobalLock(IntPtr hMem); [DllImport("kernel32.dll")] static extern bool GlobalUnlock(IntPtr hMem); [DllImport("kernel32.dll")] static extern bool GlobalFree(IntPtr hMem); private const int DM_PROMPT = 4; private const int DM_OUT_BUFFER = 2; private const int DM_IN_BUFFER = 8; private void OpenPrinterPropertiesDialog() { var printerSettings = new System.Drawing.Printing.PrinterSettings(); var printerName = printerSettings.PrinterName; IntPtr handle; OpenPrinter(printerName, out handle, IntPtr.Zero); IntPtr hDevMode = printerSettings.GetHdevmode(printerSettings.DefaultPageSettings); IntPtr pDevMode = GlobalLock(hDevMode); int sizeNeeded = DocumentProperties(this.Handle, handle, printerName, pDevMode, pDevMode, 0); IntPtr devModeData = Marshal.AllocHGlobal(sizeNeeded); DocumentProperties(this.Handle, handle, printerName, devModeData, pDevMode, DM_IN_BUFFER | DM_PROMPT | DM_OUT_BUFFER); ClosePrinter(handle); GlobalUnlock(hDevMode); printerSettings.SetHdevmode(devModeData); printerSettings.DefaultPageSettings.SetHdevmode(devModeData); GlobalFree(hDevMode); Marshal.FreeHGlobal(devModeData); }
I tried using the OpenPrinter and ClosePrinter methods and passing devModeData as the output parameter in the second call, as it was strange to me that the source code from pinvoke.net did not. (but I admit that I do not know what I'm doing - it's just a trial version and a mistake).
Here is the source code from pinvoke:
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, pDevMode, 0); IntPtr devModeData = Marshal.AllocHGlobal(sizeNeeded); DocumentProperties(this.Handle, IntPtr.Zero, printerSettings.PrinterName, IntPtr.Zero, pDevMode, 14); GlobalUnlock(hDevMode); printerSettings.SetHdevmode(devModeData); printerSettings.DefaultPageSettings.SetHdevmode(devModeData); GlobalFree(hDevMode); Marshal.FreeHGlobal(devModeData); }