Как я могу вызвать диалоговое окно для настройки параметров принтера вручную?

Я использую WPF и должен позволить пользователям устанавливать некоторые параметры, связанные с печатью, такие как свойства принтера и принтера (например, лоток для бумаги, альбомная / книжная ориентация, дуплекс и т. Д.) Мне известен класс PrintDialog для получения объектов PrintQueue и PrintTicket. Однако мне нужно создать собственное решение и я не могу показать PrintDialog. Мне удается получить доступные объекты PrintQueue и позволить пользователям выбрать принтер. Я борюсь со свойствами принтера. Мой вопрос: как я могу показать диалоговое окно, в котором пользователь может установить свойства принтера для выбранного PrintQueue (диалоговое окно, которое отображается, когда пользователь нажимает кнопку "Свойства" в WPF PrintDialog).

2 ответа

Следующий код был найден здесь (минус 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);
}

Если вы нацелены на компиляцию 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 не пытается изменить память в этой позиции. Единственными данными, возвращаемыми вызовом, является объем памяти, необходимый для хранения данных режима устройства, которые представляют внутренние параметры драйвера принтера.

Ссылка:

Другие вопросы по тегам