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

Править: Мой отказ! Я ожидал, что изменения будут записаны обратно к параметрам принтера по умолчанию, когда на самом деле только локальный экземпляр PrinterSettings изменяется. - Ниже кода, кажется, работает, как предназначено

Я пытаюсь показать пользовательские свойства принтера данного принтера. Мне нужно это как часть пользовательского PrintDialog, который я пытаюсь записать.

Большинству примеров, которые я могу найти онлайн, удается показать диалоговое окно, но любые изменения, которые мог бы внести пользователь, потеряны, который делает его бесполезным.

Пример: http://www.codeproject.com/KB/system/PrinterPropertiesWindow.aspx

(относительно вышеупомянутой страницы: Я пытался изменить код, как предложено BartJoy (на странице), но это не зафиксировало его),

Я также попробовал образец и предложения на странице pinvoke.net, но это все еще не работает:

http://www.pinvoke.net/default.aspx/winspool.documentproperties

С вышеупомянутых веб-сайтов я предполагаю, что проблема могла бы только быть в Windows на 64 бита и/или если название принтера является дольше, чем 32 символами.

Я не знаю то, что я должен попробовать затем... Я ценю любые предложения и комментарии!

Править: Вот то, что я попробовал:

[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("winspool.drv")]
private static extern int OpenPrinter(string pPrinterName, out IntPtr hPrinter, IntPtr pDefault);
[DllImport("winspool.drv")]
private static extern int ClosePrinter(IntPtr phPrinter);

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

private const int DM_PROMPT = 4;
private const int DM_OUT_BUFFER = 2;
private const int DM_IN_BUFFER = 8;

private void OpenPrinterPropertiesDialog()
{
    var printerSettings = new System.Drawing.Printing.PrinterSettings();
    var printerName = printerSettings.PrinterName;

    IntPtr handle;
    OpenPrinter(printerName, out handle, IntPtr.Zero);

    IntPtr hDevMode = printerSettings.GetHdevmode(printerSettings.DefaultPageSettings);
    IntPtr pDevMode = GlobalLock(hDevMode);
    int sizeNeeded = DocumentProperties(this.Handle, handle, printerName, pDevMode, pDevMode, 0);
    IntPtr devModeData = Marshal.AllocHGlobal(sizeNeeded);
    DocumentProperties(this.Handle, handle, printerName, devModeData, pDevMode, DM_IN_BUFFER | DM_PROMPT | DM_OUT_BUFFER);

    ClosePrinter(handle);
    GlobalUnlock(hDevMode);

    printerSettings.SetHdevmode(devModeData);
    printerSettings.DefaultPageSettings.SetHdevmode(devModeData);

    GlobalFree(hDevMode);
    Marshal.FreeHGlobal(devModeData);
}

Я попытался использовать метод OpenPrinter и ClosePrinter и передать devModeData как выходной параметр во втором вызове, поскольку я нашел это странным, что исходный код из pinvoke.net не сделал этого. (но я признаю, что я не знаю то, что я делаю - это - просто метод проб и ошибок).

Вот исходный код от pinvoke сайта:

private void OpenPrinterPropertiesDialog(PrinterSettings printerSettings)
{
    IntPtr hDevMode = printerSettings.GetHdevmode(printerSettings.DefaultPageSettings);
    IntPtr pDevMode = GlobalLock(hDevMode);
    int sizeNeeded = DocumentProperties(this.Handle, IntPtr.Zero, printerSettings.PrinterName, pDevMode, pDevMode, 0);
    IntPtr devModeData = Marshal.AllocHGlobal(sizeNeeded);
    DocumentProperties(this.Handle, IntPtr.Zero, printerSettings.PrinterName, IntPtr.Zero, pDevMode, 14);
    GlobalUnlock(hDevMode);
    printerSettings.SetHdevmode(devModeData);
    printerSettings.DefaultPageSettings.SetHdevmode(devModeData);
    GlobalFree(hDevMode);
    Marshal.FreeHGlobal(devModeData);
}

7
задан 11 revs 17 March 2010 в 00:45
поделиться

2 ответа

  • при запуске вашего приложения:
    • запросили ли вы драйвер принтера для правильного размера DEVMODE перед ее выделением?
    • Вы просили драйвер устройства инициализировать буфер DEVMODE с настройками по умолчанию после того, как вы его разместили?
  • когда ваше приложение выскакивало диалоговое окно принтера:
    • вы установили флаги DM_IN_BUFFER и DM_OUT_BUFFER (в дополнение к DM_IN_PROMPT ) в параметр fMode для DocumentProperties ?
    • указали ли вы как pDevModeInput , так и pDevModeOutput в буфер DEVMODE , вы инициализируется при запуске приложения?
    • правильно ли установлены биты dmFields в буфере DEVMODE перед вызовом DocumentProperties (... DM_IN_PROMPT ...)
    • вы сохраняете содержимое буфера DEVMODE между вызовами DocumentProperties (... DM_IN_PROMPT ...) ?

См .:

3
ответ дан 6 December 2019 в 11:48
поделиться

Кроме того, если вы хотите сделать это с помощью классов WPF (PrintQueue, PrintTicket), эта страница укажет вам правильное направление:

http://social.msdn.microsoft.com/Forums/en/wpf/thread / 0dc695c1-578d-4da5-8f68-b2a257846c02

0
ответ дан 6 December 2019 в 11:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: