首页 文章

如何调用对话框手动设置打印机选项?

提问于
浏览
5

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

2 回答

  • 3

    找到以下代码 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);
    }
    
  • 4

    如果您定位x86编译并从x64机器运行,则Pwninstein的代码将无效:当分配 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的第一次调用不会尝试修改该位置的内存 . 调用返回的唯一数据是存储表示打印驱动程序内部参数的设备模式数据所需的内存大小 .

    参考:

相关问题