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

发布于 2024-10-25 03:04:43 字数 423 浏览 4 评论 0原文

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

但是,我们将其与存储的设置结合使用。当我们使用 PrinterSettings 调用该方法时,它们会被忽略。无论提供的设置对象如何,本机对话框都会显示其默认设置。

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

We have build a custom print dialog that has a button for showing the printer specific dialog. I read this answer by Shurup, and it helped me to achieve this. (Edit: But it contains an error, as explained in my answer)

However, we use this in combination with stored settings. When we call the method with our PrinterSettings they get ignored. The native dialog shows its default settings, regardless of the provided settings object.

EDIT: Removed my fail-code.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

感谢此页面我找到了一个可行的解决方案!我链接的另一个 stackoverflow 答案中的代码包含一个小但重要的错误:对 DocumentProperties 的外部调用将输入 DEVMODE 参数定义为 ref 参数。工作解决方案不使用 ref!这看起来似乎微不足道,但实际上(至少在我的 Win32 XP 环境中)它导致打印机对话框忽略输入!

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

[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);
        }
    }
}

Thanks to this page I found a working solution! The code in the other stackoverflow answer that I linked, contained a small but significant error: The external call to DocumentProperties had the input DEVMODE parameter defined as ref parameter. The working solution doesn't use ref! This may seem insignificant, but actually (at least in my Win32 XP environment) it caused the printer dialog to ignore the input!

This code takes the settings from the PrinterSettings, sets the printer dialog accordingly and updates the PrinterSettings afterwards (you may ignore the calls to get a window handle from WPF):

[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);
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文