如何显示打印机属性/首选项对话框并保存更改?
编辑:我的错! 我希望在实际上只更改PrinterSettings的本地实例时,将更改写回默认的打印机设置。 – 以下代码似乎按预期工作
我试图显示给定打印机的自定义打印机属性。 我需要这个作为我想写的自定义PrintDialog的一部分。
我可以在网上找到的大多数示例都设法显示对话框,但用户可能做出的任何更改都会丢失,这使得它无用。
示例: http : //www.codeproject.com/KB/system/PrinterPropertiesWindow.aspx
(关于上面的页面:我试图改变BartJoy建议的代码(在页面上)但是没有修复它)
我也尝试过pinvoke.net页面上的示例和建议,但它仍然不起作用:
https://www.pinvoke.net/default.aspx/winspool.documentproperties
从上面的网站我假设问题可能只在64位Windows上和/或如果打印机名称超过32个字符。
我不知道接下来应该尝试什么…我感谢任何建议和意见!
编辑:这是我尝试过的:
[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); }
我试图使用OpenPrinter和ClosePrinter方法并在第二次调用中将devModeData作为输出参数传递,因为我发现奇怪的是pinvoke.net的原始代码没有这样做。 (但我承认,我不知道我在做什么 – 这只是反复试验)。
以下是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); }
看到:
即使答案最终成功解决问题,我认为以下内容为原始问题提供了更好的答案,
(1)因为如果用户取消,它显然不会修改传入的PrinterSettings。
(2)因为它返回一个DialogResult,调用者可能会对此感兴趣。
[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); [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); private const int DM_PROMPT = 4; private const int DM_OUT_BUFFER = 2; private const int DM_IN_BUFFER = 8; 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, pDevMode, 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; }
如果你定位x86编译并从x64机器运行,那么来自Jeff Roe的代码将不起作用:在分配devModeData
, DocumentPropreties
将始终失败并返回sizeNeeded
为-1,其LastError
代码为13。
要解决此问题,请确保将目标设为AnyCPU,或者只是将对DocumentPropreties
的调用更改为以下内容:
int sizeNeeded = DocumentProperties(pHandle, IntPtr.Zero, printerSettings.PrinterName, IntPtr.Zero, // This solves it pDevMode, fMode);
使用IntPtr.Zero
而不是指向DevMode结构的正确指针看起来是错误的,但是对DocumentProperties的第一次调用不会尝试修改该位置的内存。 调用返回的唯一数据是存储表示打印驱动程序内部参数的设备模式数据所需的内存大小。
参考:
此外,如果您想使用WPF类(PrintQueue,PrintTicket)执行此操作,此页面将指向正确的方向:
https://social.msdn.microsoft.com/Forums/en/wpf/thread/0dc695c1-578d-4da5-8f68-b2a257846c02
上述就是C#学习教程:如何显示打印机属性/首选项对话框并保存更改?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1011884.html