本文介绍了如何保存和恢复“PrinterSettings"?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个应用程序,我们想要保存 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"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-12 23:27