显示PrintDialog后修改PrinterSettings

use*_*735 5 .net c# printing winforms printer-properties

我想修改System.Drawing.Printing.PrinterSettings对象,我从System.Windows.Forms.PrintDialog得到对话框已显示给用户之后.虽然我可以在PrinterSettings对象上更改属性值,但在打印文档时实际上会考虑在显示对话框后我所做的任何更改.

这是我的意思的一个例子:

//Show the printdialog and retreive the printersettings    
var printDialog = new PrintDialog();
if (printDialog.ShowDialog() != DialogResult.OK) 
            return;
var printerSettings = printDialog.PrinterSettings;

//Now modify the printersettings object
printerSettings.ToPage = 8;
Run Code Online (Sandbox Code Playgroud)

现在使用printerSettings对象进行打印.我使用第三方dll Aspose.Words,因为我需要打印Word,但这似乎不是问题.似乎在显示对话框后,所有设置都已提交到打印机并且更改PrinterSettings什么也没做.有关如何使其工作的任何想法?

编辑:我有一些解决方法.我想要的是得到这些具体问题的答案:是否可以在显示对话框后更改PrinterSettings对象,并在打印时考虑这些更改.如果有人知道只有一个如何这样的工作方式(你可以在你想用于打印什么API决定,它不只要PrinterSettings对象使用关系),我会非常感激.

Wol*_*370 2

我在 PrintDialog 中注意到了一些事情(它可能会也可能不会回答您的问题)。

首先,它只是 Windows com 对话的包装类。

[DllImport("comdlg32.dll", CharSet=CharSet.Auto, SetLastError=true)]
        public static extern bool PrintDlg([In, Out] NativeMethods.PRINTDLG lppd);
Run Code Online (Sandbox Code Playgroud)

第二,也是最重要的,关于您的问题,我猜:PrintDialog 类有一个在 PrintDlg 调用关闭后调用的例程

if (!UnsafeNativeMethods.PrintDlg(data))
                return false;

            IntSecurity.AllPrintingAndUnmanagedCode.Assert();
            try { 
                UpdatePrinterSettings(data.hDevMode, data.hDevNames, data.nCopies, data.Flags, settings, PageSettings); 
            }
            finally { 
                CodeAccessPermission.RevertAssert();
            }
Run Code Online (Sandbox Code Playgroud)

。。。

// VSWhidbey 93449: Due to the nature of PRINTDLGEX vs PRINTDLG, separate but similar methods 
// are required for updating the settings from the structure utilized by the dialog.
// Take information from print dialog and put in PrinterSettings
private static void UpdatePrinterSettings(IntPtr hDevMode, IntPtr hDevNames, short copies, int flags, PrinterSettings settings, PageSettings pageSettings) {
        // Mode 
        settings.SetHdevmode(hDevMode);
        settings.SetHdevnames(hDevNames); 

        if (pageSettings!= null)
            pageSettings.SetHdevmode(hDevMode); 

        //Check for Copies == 1 since we might get the Right number of Copies from hdevMode.dmCopies...
        //this is Native PrintDialogs
        if (settings.Copies == 1) 
            settings.Copies = copies;

        settings.PrintRange = (PrintRange) (flags & printRangeMask); 
    }
Run Code Online (Sandbox Code Playgroud)

这里还有一个相当有趣的相互作用(记住您设置了 PrinterSettings.ToPage):

public PrinterSettings PrinterSettings {
   get { 
        if (settings == null)
        {
            settings = new PrinterSettings(); 
        }
        return settings; 
    } 
    set {
        if (value != PrinterSettings) 
        {
            settings = value;
            **printDocument = null;**
        } 
    }
} 
Run Code Online (Sandbox Code Playgroud)

进而

public PrintDocument Document {
            get { return printDocument;}
            set {
                printDocument = value; 
                **if (printDocument == null)
                    settings = new PrinterSettings();** 
                else 
                    settings = printDocument.PrinterSettings;
            } 
        }
Run Code Online (Sandbox Code Playgroud)

我知道这不是一个直接的答案,但我认为应该为您指出为什么它不起作用的正确方向。在我看来,在对话使用过程中,它可以愉快地使更改设置无效,因为它将在完成后重新创建,但是当对话完成时,更改设置实际上会使文档打印设置无效,直到再次设置为止。可以手动执行此操作,或者它可能由 M$ 以许多内部结构通常的内部/私有方式锁定。

当然,有一个选项(我知道不是那么好)在调用后直接使用 Win API - 如果需要,可以从上面的对话中提取代码来构建您自己的包装器。