РЕДАКТИРОВАТЬ: Моя вина! Я ожидал, что изменения будут записаны обратно в настройки принтера по умолчанию, хотя на самом деле изменяется только локальный экземпляр PrinterSettings. - Похоже, что приведенный ниже код работает должным образом.
Я пытаюсь показать настраиваемые свойства данного принтера. Мне это нужно как часть настраиваемого PrintDialog, который я пытаюсь написать.
В большинстве примеров, которые я могу найти в Интернете, удается показать диалоговое окно, но любые изменения, которые может внести пользователь, теряются, что делает его бесполезным.
Пример: http://www.codeproject.com/KB/system/PrinterPropertiesWindow.aspx а>
(относительно страницы выше: я попытался изменить код, как было предложено BartJoy (на странице), но это не помогло)
Я также попробовал образец и предложения на странице pinvoke.net, но он все еще не работает:
http://www.pinvoke.net/default.aspx/winspool.documentproperties
Исходя из вышеупомянутых веб-сайтов, я предполагаю, что проблема может быть только в 64-битной Windows и / или если имя принтера превышает 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);
}