2009-04-07 2 views
5

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

+0

Смотрите этот вопрос: http://stackoverflow.com/questions/2437337/how-to-show-printer-properties-preferences-dialog-and -Сохранить изменения –

ответ

4

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

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

Ссылка: