【问题标题】:How can I invoke the dialog to set printer options manually?如何调用对话框手动设置打印机选项?
【发布时间】:2010-10-18 03:49:41
【问题描述】:

我正在使用 WPF,需要让用户设置一些与打印相关的选项,例如打印机和打印机属性(例如纸盘、横向/纵向、双面打印等)。我知道 PrintDialog 类可以获取 PrintQueue 和 PrintTicket 对象。但是我需要创建自定义解决方案并且无法显示 PrintDialog。 我设法获取可用的 PrintQueue 对象并让用户选择打印机。我在打印机属性上苦苦挣扎。 我的问题是:如何显示用户可以在其中设置所选 PrintQueue 的打印机属性的对话框(当用户单击 WPF PrintDialog 中的“属性”按钮时显示的对话框)。

【问题讨论】:

标签: wpf printing printer-properties


【解决方案1】:

发现以下代码here(减去Window_Loaded事件)。我对它进行了测试,它似乎很有魅力。显然,在显示对话框之前,您必须在 PrinterSettings 对象中设置打印机名称。

希望这对你有用:

[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 Int32 DM_OUT_BUFFER = 14;

public void OpenPrinterPropertiesDialog(PrinterSettings printerSettings, System.IntPtr pHandle) {
    IntPtr hDevMode = printerSettings.GetHdevmode();
    IntPtr pDevMode = GlobalLock(hDevMode);
    Int32 fMode = 0;
    int sizeNeeded = DocumentProperties(pHandle, IntPtr.Zero, printerSettings.PrinterName, pDevMode, pDevMode, fMode);
    IntPtr devModeData = Marshal.AllocHGlobal(sizeNeeded);

    fMode = DM_OUT_BUFFER;

    DocumentProperties(pHandle, IntPtr.Zero, printerSettings.PrinterName, devModeData, pDevMode, fMode);
    GlobalUnlock(hDevMode);
    printerSettings.SetHdevmode(devModeData);
    printerSettings.DefaultPageSettings.SetHdevmode(devModeData);
    GlobalFree(hDevMode);
    Marshal.FreeHGlobal(devModeData);
}

private void Window_Loaded(object sender, RoutedEventArgs e) {
    OpenPrinterPropertiesDialog(new PrinterSettings(), new WindowInteropHelper(this).Handle);
}

【讨论】:

    【解决方案2】:

    如果您以 x86 编译为目标并从 x64 机器运行,则来自 Pwninstein 的代码将不起作用:分配 devModeData 时,DocumentPropreties 将始终失败并返回 -1 的 sizeNeededLastError代码 13。

    要解决此问题,请确保您以 AnyCPU 为目标,或者只需将对 DocumentPropreties 的调用更改为以下内容:

    int sizeNeeded = DocumentProperties(pHandle, 
                                        IntPtr.Zero, 
                                        printerSettings.PrinterName, 
                                        IntPtr.Zero, // This solves it
                                        pDevMode, 
                                        fMode);
    

    使用IntPtr.Zero 而不是正确的指向 DevMode 结构的指针看起来是错误的,但是第一次调用 DocumentProperties 并不会尝试修改该位置的内存。调用返回的唯一数据是存储表示打印驱动程序内部参数的设备模式数据所需的内存大小。

    参考:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-10
      • 2011-02-18
      • 1970-01-01
      • 2013-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多