问题描述
我有一个应用程序,我们想要保存 PrinterSettings
用户选择注册表,然后在我们准备打印时恢复它们.有没有办法序列化PrinterSettings
?
I have an application which we want to save the PrinterSettings
a user selects to the registry, then restore them when we are ready to print. Is there a way to serialize PrinterSettings
?
推荐答案
PrinterSettings
的全部内容 –包括供应商特定选项–可以通过持久化通过PrinterSettings.GetHdevmode()
接收到的HDEVMODE
结构来存储,然后通过PrinterSettings.SetHdevmode(IntPtr)
恢复.
The entirety of the PrinterSettings
– including vendor specific options – can be stored by persisting the HDEVMODE
structure received via PrinterSettings.GetHdevmode()
, then restored via PrinterSettings.SetHdevmode(IntPtr)
.
下面的类将添加两个扩展方法,用于在 byte
数组中保存和恢复 PrinterSettings
.
The class below will add two extension methods to save and restore PrinterSettings
to and from a byte
array.
警告程序员:某些打印机驱动程序没有向后或向前兼容性,如果使用来自其他版本或驱动程序架构的持久数据,可能会崩溃.
Caveat programmer: some printer drivers do not have backwards or forwards compatibility, and may crash if using persisted data from another version or architecture of the driver.
示例使用:
PrinterSettings CurrentSettings;
const string myAppKeyName = @"Software\MyApplicationName";
const string printerSettingValueName = "PrinterSettings"
// save
using (var sk = Registry.CurrentUser.CreateSubKey(myAppKeyName))
{
sk.SetValue(printerSettingValueName, this.CurrentSettings.GetDevModeData(), RegistryValueKind.Binary);
}
// restore
using (var sk = Registry.CurrentUser.CreateSubKey(myAppKeyName))
{
var data = sk.GetValue(printerSettingValueName, RegistryValueKind.Binary) as byte[];
this.CurrentSettings = new PrinterSettings();
if (data != null)
{
this.CurrentSettings.SetDevModeData(data);
}
}
实施:
static class PrinterSettingsExtensions
{
public static byte[] GetDevModeData(this PrinterSettings settings)
{
//Contract.Requires(settings != null);
byte[] devModeData;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
// cer since hDevMode is not a SafeHandle
}
finally
{
var hDevMode = settings.GetHdevmode();
try
{
IntPtr pDevMode = NativeMethods.GlobalLock(hDevMode);
try
{
var devMode = (NativeMethods.DEVMODE)Marshal.PtrToStructure(
pDevMode, typeof(NativeMethods.DEVMODE));
var devModeSize = devMode.dmSize + devMode.dmDriverExtra;
devModeData = new byte[devModeSize];
Marshal.Copy(pDevMode, devModeData, 0, devModeSize);
}
finally
{
NativeMethods.GlobalUnlock(hDevMode);
}
}
finally
{
Marshal.FreeHGlobal(hDevMode);
}
}
return devModeData;
}
public static void SetDevModeData(this PrinterSettings settings, byte[] data)
{
//Contract.Requires(settings != null);
//Contract.Requires(data != null);
//Contract.Requires(data.Length >= Marshal.SizeOf(typeof(NativeMethods.DEVMODE)));
RuntimeHelpers.PrepareConstrainedRegions();
try
{
// cer since AllocHGlobal does not return SafeHandle
}
finally
{
var pDevMode = Marshal.AllocHGlobal(data.Length);
try
{
// we don't have to worry about GlobalLock since AllocHGlobal only uses LMEM_FIXED
Marshal.Copy(data, 0, pDevMode, data.Length);
var devMode = (NativeMethods.DEVMODE)Marshal.PtrToStructure(
pDevMode, typeof(NativeMethods.DEVMODE));
// The printer name must match the original printer, otherwise an AV will be thrown
settings.PrinterName = devMode.dmDeviceName;
// SetHDevmode creates a copy of the devmode, so we don't have to keep ours around
settings.SetHdevmode(pDevMode);
}
finally
{
Marshal.FreeHGlobal(pDevMode);
}
}
}
}
static class NativeMethods
{
private const string Kernel32 = "kernel32.dll";
[DllImport(Kernel32, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Auto)]
public static extern IntPtr GlobalLock(IntPtr handle);
[DllImport(Kernel32, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Auto)]
public static extern bool GlobalUnlock(IntPtr handle);
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Auto)]
public struct DEVMODE
{
private const int CCHDEVICENAME = 32;
private const int CCHFORMNAME = 32;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)]
public string dmDeviceName;
public short dmSpecVersion;
public short dmDriverVersion;
public short dmSize;
public short dmDriverExtra;
public int dmFields;
public int dmPositionX;
public int dmPositionY;
public int dmDisplayOrientation;
public int dmDisplayFixedOutput;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHFORMNAME)]
public string dmFormName;
public short dmLogPixels;
public int dmBitsPerPel;
public int dmPelsWidth;
public int dmPelsHeight;
public int dmDisplayFlags;
public int dmDisplayFrequency;
public int dmICMMethod;
public int dmICMIntent;
public int dmMediaType;
public int dmDitherType;
public int dmReserved1;
public int dmReserved2;
public int dmPanningWidth;
public int dmPanningHeight;
}
}
相关:
这篇关于如何保存和恢复“PrinterSettings"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!