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