4

我需要更改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使用 aNullReferenceException并且没有任何有意义的错误信息执行时,它会失败。d.PrinterSettings不为 null,则在方法内部引发异常PrinterSettings.SetHdevmode
所以我的问题是:出了什么问题?是投错了吗byte[]IntPtr也许期望数组SetHdevmode以外的东西?byte[]

byte[] devmode_data从注册表中获取数组。这是一个有效值,并且与当前打印机设置中使用的值相同。

4

2 回答 2

1

我通过以下方式修改了您的代码,因为我没有任何有效数据devmode_data

devmode = d.PrinterSettings.GetHdevmode();
if (devmode != IntPtr.Zero) d.PrinterSettings.SetHdevmode(devmode);

现在这里也不例外。

请向我提供您的数据devmode_data或检查您自己的数据是否有效!

于 2011-11-27T00:28:40.010 回答
1

SetHdevmode期望一个HGLOBAL. 您可以HGLOBAL通过 .Net 从 .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结构是可变长度的,以允许打印机驱动程序添加额外的不透明数据,因此无法在不丢失数据的情况下进行转换。

请参阅如何保存和恢复“打印机设置”?更多。

于 2015-01-18T06:08:20.700 回答