Не могу изменить DEVMODE принтера
Мне нужно изменить DEVMODE
принтера для текущей задачи печати, чтобы пройти стандартные и специфичные для устройства настройки. Я делаю следующее:
PrintDocument d = new PrintDocument();
d.PrinterSettings.PrinterName = "Microsoft XPS Document Writer"; // example printer name
byte[] devmode_data; // contains a valid value that is obtained from registry
IntPtr devmode = IntPtr.Zero;
GCHandle handle = GCHandle.Alloc(devmode_data, GCHandleType.Pinned);
try
{
devmode = handle.AddrOfPinnedObject();
if (devmode != IntPtr.Zero) d.PrinterSettings.SetHdevmode(devmode);
}
finally
{
if (handle.IsAllocated) handle.Free();
}
Не удается, когда я пытаюсь выполнить PrinterSettings.SetHdevmode
с NullReferenceException
и без какой-либо значимой информации об ошибке. d.PrinterSettings
не является нулевым, исключение выбрасывается внутри PrinterSettings.SetHdevmode
метод.
Итак, мой вопрос: что не так? Это byte[]
в IntPtr
бросить неправильно? Может быть SetHdevmode
ожидает что-то другое, чем byte[]
массив?
Я получаю byte[] devmode_data
массив из реестра. Это допустимое значение, и это то же значение, которое используется в текущих настройках принтера.
2 ответа
Я изменил ваш код следующим образом, поскольку у меня нет действительных данных для devmode_data
:
devmode = d.PrinterSettings.GetHdevmode();
if (devmode != IntPtr.Zero) d.PrinterSettings.SetHdevmode(devmode);
и теперь здесь нет исключений.
Пожалуйста, предоставьте мне ваши данные для devmode_data
или проверьте свой, действителен ли он или нет!
SetHdevmode
ожидает HGLOBAL
, Вы можете получить HGLOBAL
из.Net через Marshal.AllocHGlobal
, Затем вы можете использовать Marshal.Copy(byte[], int, IntPtr, int)
скопировать из вашего управляемого байтового массива в HGLOBAL
, Увидеть ниже:
var pDevMode = Marshal.AllocHGlobal(devmode_data.Length);
Marshal.Copy(devmode_data, 0, pDevMode, devmode_data.Length);
d.PrinterSettings.SetHdevmode(pDevMode);
Marshal.FreeHGlobal(pDevMode);
Массив байтов может быть частично обработан как структура, но для этого потребуются определения p/Invoke. PrinterSettings
Класс, однако, не примет структуру, поэтому в этом случае это не потребуется. Кроме того, DEVMODE
Структура переменной длины, позволяющая драйверам принтера добавлять дополнительные непрозрачные данные, поэтому преобразование невозможно без потери данных.
См. Как я могу сохранить и восстановить `PrinterSettings`? для большего.