C# 修改打印机特定配置对话框的属性

C# 修改打印机特定配置对话框的属性,c#,printing,gdi,C#,Printing,Gdi,我们构建了一个自定义打印对话框,其中有一个按钮用于显示特定于打印机的对话框。我通过阅读,它帮助我实现了这一目标。(编辑:但它包含一个错误,如我的回答中所述) 但是,我们将其与存储设置结合使用。当我们使用PrinterSettings调用方法时,它们会被忽略。本机对话框显示其默认设置,而不管提供的设置对象是什么 编辑:删除了我的失败代码。多亏我找到了一个有效的解决方案!我链接的另一个stackoverflow答案中的代码包含一个小但重要的错误:对DocumentProperties的外部调用将输入

我们构建了一个自定义打印对话框,其中有一个按钮用于显示特定于打印机的对话框。我通过阅读,它帮助我实现了这一目标。(编辑:但它包含一个错误,如我的回答中所述)

但是,我们将其与存储设置结合使用。当我们使用
PrinterSettings
调用方法时,它们会被忽略。本机对话框显示其默认设置,而不管提供的设置对象是什么

编辑:删除了我的失败代码。

多亏我找到了一个有效的解决方案!我链接的另一个stackoverflow答案中的代码包含一个小但重要的错误:对
DocumentProperties
的外部调用将输入DEVMODE参数定义为
ref
参数。工作解决方案不使用ref!这似乎无关紧要,但实际上(至少在我的Win32 XP环境中)它导致打印机对话框忽略输入

此代码从PrinterSettings获取设置,相应地设置打印机对话框,然后更新PrinterSettings(您可以忽略从WPF获取窗口句柄的调用):


也许您可以使用本文中描述的函数GetProfileString/GetProfileInt等:谢谢,但是获取设置并保存它们没有问题。打印对话框将设置放入给定的
PrinterSettings
,以便我以后可以检索它们。问题是对话框显然忽略了我给它的设置。它总是显示默认设置,不管我事先在PrinterSettings中输入了什么。有什么帮助吗?
[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("kernel32.dll")]
static extern IntPtr GlobalLock(IntPtr hMem);

[DllImport("kernel32.dll")]
static extern bool GlobalUnlock(IntPtr hMem);

private void OpenPrinterPropertiesDialog(PrinterSettings printerSettings)
{
    Window parentWindow = Window.GetWindow(this);
    if (parentWindow == null)
    {
        return;
    }
    IntPtr hDevMode = IntPtr.Zero;
    IntPtr devModeData = IntPtr.Zero;
    try
    {
        IntPtr hwnd = new System.Windows.Interop.WindowInteropHelper(parentWindow).Handle;
        //get DEVMODE from settings
        hDevMode = printerSettings.GetHdevmode(printerSettings.DefaultPageSettings);
        IntPtr pDevMode = GlobalLock(hDevMode);
        //get needed size and allocate memory
        int sizeNeeded = DocumentProperties(hwnd, IntPtr.Zero, printerSettings.PrinterName, IntPtr.Zero, pDevMode, 0);
        devModeData = Marshal.AllocHGlobal(sizeNeeded);
        //show the native dialog
        DocumentProperties(hwnd, IntPtr.Zero, printerSettings.PrinterName, devModeData, pDevMode, 14);
        GlobalUnlock(hDevMode);
        //get settings and page settings from changed DEVMODE
        printerSettings.SetHdevmode(devModeData);
        printerSettings.DefaultPageSettings.SetHdevmode(devModeData);
    }
    finally
    {
        if (hDevMode != IntPtr.Zero)
        {
            Marshal.FreeHGlobal(hDevMode);
        }
        if (devModeData != IntPtr.Zero)
        {
            Marshal.FreeHGlobal(devModeData);
        }
    }
}