namespace Frame.Printer
{
    /// <summary>
    ///
    /// </summary>
    public class PrinterHelper
    {
        private PrinterHelper()
        {
        }

#region API声明
        /// <summary>
        ///
        /// </summary>
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        internal struct structPrinterDefaults
        {
            [MarshalAs(UnmanagedType.LPTStr)]
            public String pDatatype;
            public IntPtr pDevMode;
            [MarshalAs(UnmanagedType.I4)]
            public int DesiredAccess;
        };

/// <summary>
        ///
        /// </summary>
        /// <param name="printerName"></param>
        /// <param name="phPrinter"></param>
        /// <param name="pd"></param>
        /// <returns></returns>
        [DllImport("winspool.Drv", EntryPoint = "OpenPrinter", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = false, CallingConvention = CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()]
        internal static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPTStr)] string printerName, out IntPtr phPrinter, ref structPrinterDefaults pd);

/// <summary>
        ///
        /// </summary>
        /// <param name="phPrinter"></param>
        /// <returns></returns>
        [DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = false, CallingConvention = CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()]
        internal static extern bool ClosePrinter(IntPtr phPrinter);

/// <summary>
        ///
        /// </summary>
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        internal struct structSize
        {
            public Int32 width;
            public Int32 height;
        }

/// <summary>
        ///
        /// </summary>
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        internal struct structRect
        {
            public Int32 left;
            public Int32 top;
            public Int32 right;
            public Int32 bottom;
        }

/// <summary>
        ///
        /// </summary>
        [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)]
        internal struct FormInfo1
        {
            [FieldOffset(0), MarshalAs(UnmanagedType.I4)]
            public uint Flags;
            [FieldOffset(4), MarshalAs(UnmanagedType.LPWStr)]
            public String pName;
            [FieldOffset(8)]
            public structSize Size;
            [FieldOffset(16)]
            public structRect ImageableArea;
        };

/// <summary>
        ///
        /// </summary>
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        internal struct structDevMode
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public String
             dmDeviceName;
            [MarshalAs(UnmanagedType.U2)]
            public short dmSpecVersion;
            [MarshalAs(UnmanagedType.U2)]
            public short dmDriverVersion;
            [MarshalAs(UnmanagedType.U2)]
            public short dmSize;
            [MarshalAs(UnmanagedType.U2)]
            public short dmDriverExtra;
            [MarshalAs(UnmanagedType.U4)]
            public int dmFields;
            [MarshalAs(UnmanagedType.I2)]
            public short dmOrientation;
            [MarshalAs(UnmanagedType.I2)]
            public short dmPaperSize;
            [MarshalAs(UnmanagedType.I2)]
            public short dmPaperLength;
            [MarshalAs(UnmanagedType.I2)]
            public short dmPaperWidth;
            [MarshalAs(UnmanagedType.I2)]
            public short dmScale;
            [MarshalAs(UnmanagedType.I2)]
            public short dmCopies;
            [MarshalAs(UnmanagedType.I2)]
            public short dmDefaultSource;
            [MarshalAs(UnmanagedType.I2)]
            public short dmPrintQuality;
            [MarshalAs(UnmanagedType.I2)]
            public short dmColor;
            [MarshalAs(UnmanagedType.I2)]
            public short dmDuplex;
            [MarshalAs(UnmanagedType.I2)]
            public short dmYResolution;
            [MarshalAs(UnmanagedType.I2)]
            public short dmTTOption;
            [MarshalAs(UnmanagedType.I2)]
            public short dmCollate;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public String dmFormName;
            [MarshalAs(UnmanagedType.U2)]
            public short dmLogPixels;
            [MarshalAs(UnmanagedType.U4)]
            public int dmBitsPerPel;
            [MarshalAs(UnmanagedType.U4)]
            public int dmPelsWidth;
            [MarshalAs(UnmanagedType.U4)]
            public int dmPelsHeight;
            [MarshalAs(UnmanagedType.U4)]
            public int dmNup;
            [MarshalAs(UnmanagedType.U4)]
            public int dmDisplayFrequency;
            [MarshalAs(UnmanagedType.U4)]
            public int dmICMMethod;
            [MarshalAs(UnmanagedType.U4)]
            public int dmICMIntent;
            [MarshalAs(UnmanagedType.U4)]
            public int dmMediaType;
            [MarshalAs(UnmanagedType.U4)]
            public int dmDitherType;
            [MarshalAs(UnmanagedType.U4)]
            public int dmReserved1;
            [MarshalAs(UnmanagedType.U4)]
            public int dmReserved2;
        }

/// <summary>
        ///
        /// </summary>
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        internal struct PRINTER_INFO_9
        {
            public IntPtr pDevMode;
        }

/// <summary>
        ///
        /// </summary>
        /// <param name="phPrinter"></param>
        /// <param name="level"></param>
        /// <param name="form"></param>
        /// <returns></returns>
        [DllImport("winspool.Drv", EntryPoint = "AddFormW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()]
        internal static extern bool AddForm(IntPtr phPrinter, [MarshalAs(UnmanagedType.I4)] int level, ref FormInfo1 form);

/// <summary>
        ///
        /// </summary>
        /// <param name="phPrinter"></param>
        /// <param name="pName"></param>
        /// <returns></returns>
        [DllImport("winspool.Drv", EntryPoint = "DeleteForm", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = false, CallingConvention = CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()]
        internal static extern bool DeleteForm(IntPtr phPrinter, [MarshalAs(UnmanagedType.LPTStr)] string pName);

/// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        [DllImport("kernel32.dll", EntryPoint = "GetLastError", SetLastError = false, ExactSpelling = true, CallingConvention = CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()]
        internal static extern Int32 GetLastError();

/// <summary>
        ///
        /// </summary>
        /// <param name="pDrive"></param>
        /// <param name="pName"></param>
        /// <param name="pOutput"></param>
        /// <param name="pDevMode"></param>
        /// <returns></returns>
        [DllImport("GDI32.dll", EntryPoint = "CreateDC", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = false, CallingConvention = CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()]
        internal static extern IntPtr CreateDC([MarshalAs(UnmanagedType.LPTStr)] string pDrive, [MarshalAs(UnmanagedType.LPTStr)] string pName, [MarshalAs(UnmanagedType.LPTStr)] string pOutput, ref structDevMode pDevMode);

[DllImport("GDI32.dll", EntryPoint = "ResetDC", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = false, CallingConvention = CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()]
        internal static extern IntPtr ResetDC(IntPtr hDC, ref structDevMode pDevMode);

/// <summary>
        ///
        /// </summary>
        /// <param name="hDC"></param>
        /// <returns></returns>
        [DllImport("GDI32.dll", EntryPoint = "DeleteDC", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = false, CallingConvention = CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()]
        internal static extern bool DeleteDC(IntPtr hDC);

/// <summary>
        ///
        /// </summary>
        /// <param name="hPrinter"></param>
        /// <param name="level"></param>
        /// <param name="pPrinter"></param>
        /// <param name="command"></param>
        /// <returns></returns>
        [DllImport("winspool.Drv", EntryPoint = "SetPrinterA", SetLastError = true, CharSet = CharSet.Auto, ExactSpelling = true, CallingConvention = CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()]
        internal static extern bool SetPrinter(IntPtr hPrinter, [MarshalAs(UnmanagedType.I4)] int level, IntPtr pPrinter, [MarshalAs(UnmanagedType.I4)] int command);

/// <summary>
        ///
        /// </summary>
        /// <param name="hwnd"></param>
        /// <param name="hPrinter"></param>
        /// <param name="pDeviceName"></param>
        /// <param name="pDevModeOutput"></param>
        /// <param name="pDevModeInput"></param>
        /// <param name="fMode"></param>
        /// <returns></returns>
        [DllImport("winspool.Drv", EntryPoint = "DocumentPropertiesA", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        internal static extern int DocumentProperties(IntPtr hwnd, IntPtr hPrinter, [MarshalAs(UnmanagedType.LPStr)] string pDeviceName, IntPtr pDevModeOutput, IntPtr pDevModeInput, int fMode);

/// <summary>
        ///
        /// </summary>
        /// <param name="hPrinter"></param>
        /// <param name="dwLevel"></param>
        /// <param name="pPrinter"></param>
        /// <param name="dwBuf"></param>
        /// <param name="dwNeeded"></param>
        /// <returns></returns>
        [DllImport("winspool.Drv", EntryPoint = "GetPrinterA", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        internal static extern bool GetPrinter(IntPtr hPrinter, int dwLevel, IntPtr pPrinter, int dwBuf, out int dwNeeded);

/// <summary>
        ///
        /// </summary>
        [Flags]
        internal enum SendMessageTimeoutFlags : uint
        {
            SMTO_NORMAL = 0x0000,
            SMTO_BLOCK = 0x0001,
            SMTO_ABORTIFHUNG = 0x0002,
            SMTO_NOTIMEOUTIFNOTHUNG = 0x0008
        }

const int WM_SETTINGCHANGE = 0x001A;
        const int HWND_BROADCAST = 0xffff;

/// <summary>
        ///
        /// </summary>
        /// <param name="windowHandle"></param>
        /// <param name="Msg"></param>
        /// <param name="wParam"></param>
        /// <param name="lParam"></param>
        /// <param name="flags"></param>
        /// <param name="timeout"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        internal static extern IntPtr SendMessageTimeout(IntPtr windowHandle, uint Msg, IntPtr wParam, IntPtr lParam, SendMessageTimeoutFlags flags, uint timeout, out IntPtr result);

/// <summary>
        /// EnumPrinters用到的函数和结构体
        /// </summary>
        /// <param name="Flags"></param>
        /// <param name="Name"></param>
        /// <param name="Level"></param>
        /// <param name="pPrinterEnum"></param>
        /// <param name="cbBuf"></param>
        /// <param name="pcbNeeded"></param>
        /// <param name="pcReturned"></param>
        /// <returns></returns>
        [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool EnumPrinters(PrinterEnumFlags Flags, string Name, uint Level, IntPtr pPrinterEnum, uint cbBuf, ref uint pcbNeeded, ref uint pcReturned);

/// <summary>
        ///
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        internal struct PRINTER_INFO_2
        {
            public string pServerName;
            public string pPrinterName;
            public string pShareName;
            public string pPortName;
            public string pDriverName;
            public string pComment;
            public string pLocation;
            public IntPtr pDevMode;
            public string pSepFile;
            public string pPrintProcessor;
            public string pDatatype;
            public string pParameters;
            public IntPtr pSecurityDescriptor;
            public uint Attributes;
            public uint Priority;
            public uint DefaultPriority;
            public uint StartTime;
            public uint UntilTime;
            public uint Status;
            public uint cJobs;
            public uint AveragePPM;
        }

/// <summary>
        ///
        /// </summary>
        [FlagsAttribute]
        internal enum PrinterEnumFlags
        {
            PRINTER_ENUM_DEFAULT = 0x00000001,
            PRINTER_ENUM_LOCAL = 0x00000002,
            PRINTER_ENUM_CONNECTIONS = 0x00000004,
            PRINTER_ENUM_FAVORITE = 0x00000004,
            PRINTER_ENUM_NAME = 0x00000008,
            PRINTER_ENUM_REMOTE = 0x00000010,
            PRINTER_ENUM_SHARED = 0x00000020,
            PRINTER_ENUM_NETWORK = 0x00000040,
            PRINTER_ENUM_EXPAND = 0x00004000,
            PRINTER_ENUM_CONTAINER = 0x00008000,
            PRINTER_ENUM_ICONMASK = 0x00ff0000,
            PRINTER_ENUM_ICON1 = 0x00010000,
            PRINTER_ENUM_ICON2 = 0x00020000,
            PRINTER_ENUM_ICON3 = 0x00040000,
            PRINTER_ENUM_ICON4 = 0x00080000,
            PRINTER_ENUM_ICON5 = 0x00100000,
            PRINTER_ENUM_ICON6 = 0x00200000,
            PRINTER_ENUM_ICON7 = 0x00400000,
            PRINTER_ENUM_ICON8 = 0x00800000,
            PRINTER_ENUM_HIDE = 0x01000000
        }

/// <summary>
        /// 打印机状态
        /// </summary>
        [FlagsAttribute]
        internal enum PrinterStatus
        {
            PRINTER_STATUS_BUSY = 0x00000200,
            PRINTER_STATUS_DOOR_OPEN = 0x00400000,
            PRINTER_STATUS_ERROR = 0x00000002,
            PRINTER_STATUS_INITIALIZING = 0x00008000,
            PRINTER_STATUS_IO_ACTIVE = 0x00000100,
            PRINTER_STATUS_MANUAL_FEED = 0x00000020,
            PRINTER_STATUS_NO_TONER = 0x00040000,
            PRINTER_STATUS_NOT_AVAILABLE = 0x00001000,
            PRINTER_STATUS_OFFLINE = 0x00000080,
            PRINTER_STATUS_OUT_OF_MEMORY = 0x00200000,
            PRINTER_STATUS_OUTPUT_BIN_FULL = 0x00000800,
            PRINTER_STATUS_PAGE_PUNT = 0x00080000,
            PRINTER_STATUS_PAPER_JAM = 0x00000008,
            PRINTER_STATUS_PAPER_OUT = 0x00000010,
            PRINTER_STATUS_PAPER_PROBLEM = 0x00000040,
            PRINTER_STATUS_PAUSED = 0x00000001,
            PRINTER_STATUS_PENDING_DELETION = 0x00000004,
            PRINTER_STATUS_PRINTING = 0x00000400,
            PRINTER_STATUS_PROCESSING = 0x00004000,
            PRINTER_STATUS_TONER_LOW = 0x00020000,
            PRINTER_STATUS_USER_INTERVENTION = 0x00100000,
            PRINTER_STATUS_WAITING = 0x20000000,
            PRINTER_STATUS_WARMING_UP = 0x00010000
        }

/// <summary>
        /// GetDefaultPrinter用到的API函数说明
        /// </summary>
        /// <param name="pszBuffer"></param>
        /// <param name="size"></param>
        /// <returns></returns>
        [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
        internal static extern bool GetDefaultPrinter(StringBuilder pszBuffer, ref int size);

/// <summary>
        /// SetDefaultPrinter用到的API函数声明
        /// </summary>
        /// <param name="Name"></param>
        /// <returns></returns>
        [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
        internal static extern bool SetDefaultPrinter(string Name);

/// <summary>
        /// EnumFormsA用到的函数声明,应该和EnumPrinters类似
        /// </summary>
        /// <param name="hPrinter"></param>
        /// <param name="Level"></param>
        /// <param name="pForm"></param>
        /// <param name="cbBuf"></param>
        /// <param name="pcbNeeded"></param>
        /// <param name="pcReturned"></param>
        /// <returns></returns>
        [DllImport("winspool.drv", EntryPoint = "EnumForms")]
        internal static extern int EnumFormsA(IntPtr hPrinter, int Level, ref byte pForm, int cbBuf, ref int pcbNeeded, ref int pcReturned);

#endregion   API声明
        /// <summary>
        ///
        /// </summary>
        /// <param name="PrinterName"></param>
        /// <returns></returns>
        internal static int GetPrinterStatusInt(string PrinterName)
        {
            int intRet = 0;
            IntPtr hPrinter;
            structPrinterDefaults defaults = new structPrinterDefaults();
            if (OpenPrinter(PrinterName, out hPrinter, ref defaults))
            {
                int cbNeeded = 0;
                bool bolRet = GetPrinter(hPrinter, 2, IntPtr.Zero, 0, out cbNeeded);
                if (cbNeeded > 0)
                {
                    IntPtr pAddr = Marshal.AllocHGlobal((int)cbNeeded);
                    bolRet = GetPrinter(hPrinter, 2, pAddr, cbNeeded, out cbNeeded);
                    if (bolRet)
                    {
                        PRINTER_INFO_2 Info2 = new PRINTER_INFO_2();
                        Info2 = (PRINTER_INFO_2)Marshal.PtrToStructure(pAddr, typeof(PRINTER_INFO_2));
                        intRet = System.Convert.ToInt32(Info2.Status);
                    }
                    Marshal.FreeHGlobal(pAddr);
                }
                ClosePrinter(hPrinter);
            }
            return intRet;
        }

/// <summary>
        ///
        /// </summary>
        /// <param name="Flags"></param>
        /// <returns></returns>
        internal static PRINTER_INFO_2[] EnumPrintersByFlag(PrinterEnumFlags Flags)
        {
            uint cbNeeded = 0;
            uint cReturned = 0;
            bool ret = EnumPrinters(PrinterEnumFlags.PRINTER_ENUM_LOCAL, null, 2, IntPtr.Zero, 0, ref cbNeeded, ref cReturned);
            IntPtr pAddr = Marshal.AllocHGlobal((int)cbNeeded);
            ret = EnumPrinters(PrinterEnumFlags.PRINTER_ENUM_LOCAL, null, 2, pAddr, cbNeeded, ref cbNeeded, ref cReturned);
            if (ret)
            {
                PRINTER_INFO_2[] Info2 = new PRINTER_INFO_2[cReturned];
                int offset = pAddr.ToInt32();
                for (int i = 0; i < cReturned; i++)
                {
                    Info2[i].pServerName = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
                    offset += 4;
                    Info2[i].pPrinterName = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
                    offset += 4;
                    Info2[i].pShareName = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
                    offset += 4;
                    Info2[i].pPortName = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
                    offset += 4;
                    Info2[i].pDriverName = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
                    offset += 4;
                    Info2[i].pComment = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
                    offset += 4;
                    Info2[i].pLocation = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
                    offset += 4;
                    Info2[i].pDevMode = Marshal.ReadIntPtr(new IntPtr(offset));
                    offset += 4;
                    Info2[i].pSepFile = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
                    offset += 4;
                    Info2[i].pPrintProcessor = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
                    offset += 4;
                    Info2[i].pDatatype = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
                    offset += 4;
                    Info2[i].pParameters = Marshal.PtrToStringAuto(Marshal.ReadIntPtr(new IntPtr(offset)));
                    offset += 4;
                    Info2[i].pSecurityDescriptor = Marshal.ReadIntPtr(new IntPtr(offset));
                    offset += 4;
                    Info2[i].Attributes = (uint)Marshal.ReadIntPtr(new IntPtr(offset));
                    offset += 4;
                    Info2[i].Priority = (uint)Marshal.ReadInt32(new IntPtr(offset));
                    offset += 4;
                    Info2[i].DefaultPriority = (uint)Marshal.ReadInt32(new IntPtr(offset));
                    offset += 4;
                    Info2[i].StartTime = (uint)Marshal.ReadInt32(new IntPtr(offset));
                    offset += 4;
                    Info2[i].UntilTime = (uint)Marshal.ReadInt32(new IntPtr(offset));
                    offset += 4;
                    Info2[i].Status = (uint)Marshal.ReadInt32(new IntPtr(offset));
                    offset += 4;
                    Info2[i].cJobs = (uint)Marshal.ReadInt32(new IntPtr(offset));
                    offset += 4;
                    Info2[i].AveragePPM = (uint)Marshal.ReadInt32(new IntPtr(offset));
                    offset += 4;
                }
                Marshal.FreeHGlobal(pAddr);
                return Info2;
            }
            else
            {
                return new PRINTER_INFO_2[0];
            }
        }
        #region 获取当前指定打印机的状态
        /// <summary>
        /// 获取当前指定打印机的状态
        /// </summary>
        /// <param name="printerName"></param>
        /// <returns></returns>
        public static string GetPrinterStatus(string printerName)
        {
            int intValue = GetPrinterStatusInt(printerName);
            string strRet = string.Empty;
            switch (intValue)
            {
                case 0:
                    strRet = "准备就绪(Ready)";
                    break;
                case 0x00000200:
                    strRet = "忙(Busy)";
                    break;
                case 0x00400000:
                    strRet = "门被打开(Printer Door Open)";
                    break;
                case 0x00000002:
                    strRet = "错误(Printer Error)";
                    break;
                case 0x0008000:
                    strRet = "正在初始化(Initializing)";
                    break;
                case 0x00000100:
                    strRet = "正在输入或输出(I/O Active)";
                    break;
                case 0x00000020:
                    strRet = "手工送纸(Manual Feed)";
                    break;
                case 0x00040000:
                    strRet = "无墨粉(No Toner)";
                    break;
                case 0x00001000:
                    strRet = "不可用(Not Available)";
                    break;
                case 0x00000080:
                    strRet = "脱机(Off Line)";
                    break;
                case 0x00200000:
                    strRet = "内存溢出(Out of Memory)";
                    break;
                case 0x00000800:
                    strRet = "输出口已满(Output Bin Full)";
                    break;
                case 0x00080000:
                    strRet = "当前页无法打印(Page Punt)";
                    break;
                case 0x00000008:
                    strRet = "塞纸(Paper Jam)";
                    break;
                case 0x00000010:
                    strRet = "打印纸用完(Paper Out)";
                    break;
                case 0x00000040:
                    strRet = "纸张问题(Page Problem)";
                    break;
                case 0x00000001:
                    strRet = "暂停(Paused)";
                    break;
                case 0x00000004:
                    strRet = "正在删除(Pending Deletion)";
                    break;
                case 0x00000400:
                    strRet = "正在打印(Printing)";
                    break;
                case 0x00004000:
                    strRet = "正在处理(Processing)";
                    break;
                case 0x00020000:
                    strRet = "墨粉不足(Toner Low)";
                    break;
                case 0x00100000:
                    strRet = "需要用户干预(User Intervention)";
                    break;
                case 0x20000000:
                    strRet = "等待(Waiting)";
                    break;
                case 0x00010000:
                    strRet = "正在准备(Warming Up)";
                    break;
                default:
                    strRet = "未知状态(Unknown Status)";
                    break;
            }
            return strRet;
        }
        #endregion 获取当前指定打印机的状态
        #region 删除已经存在的自定义纸张
        /// <summary>
        /// 删除已经存在的自定义纸张
        /// </summary>
        /// <param name="PrinterName">打印机名称</param>
        /// <param name="PaperName">纸张名称</param>
        public static void DeleteCustomPaperSize(string PrinterName, string PaperName)
        {
            const int PRINTER_ACCESS_USE = 0x00000008;
            const int PRINTER_ACCESS_ADMINISTER = 0x00000004;

structPrinterDefaults defaults = new structPrinterDefaults();
            defaults.pDatatype = null;
            defaults.pDevMode = IntPtr.Zero;
            defaults.DesiredAccess = PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE;

IntPtr hPrinter = IntPtr.Zero;

//打开打印机
            if (OpenPrinter(PrinterName, out hPrinter, ref defaults))
            {
                try
                {
                    DeleteForm(hPrinter, PaperName);
                    ClosePrinter(hPrinter);
                }
                catch
                {

}
            }
        }
        #endregion 删除已经存在的自定义纸张
        #region 指定的打印机设置以mm为单位的自定义纸张(Form)
        /// <summary>
        /// 指定的打印机设置以mm为单位的自定义纸张(Form)
        /// </summary>
        /// <param name="PrinterName">打印机名称</param>
        /// <param name="PaperName">Form名称</param>
        /// <param name="WidthInMm">以mm为单位的宽度</param>
        /// <param name="HeightInMm">以mm为单位的高度</param>
        public static void AddCustomPaperSize(string PrinterName, string PaperName, float WidthInMm, float HeightInMm)
        {
            if (PlatformID.Win32NT == Environment.OSVersion.Platform)
            {
                const int PRINTER_ACCESS_USE = 0x00000008;
                const int PRINTER_ACCESS_ADMINISTER = 0x00000004;
                structPrinterDefaults defaults = new structPrinterDefaults();
                defaults.pDatatype = null;
                defaults.pDevMode = IntPtr.Zero;
                defaults.DesiredAccess = PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE;
                IntPtr hPrinter = IntPtr.Zero;
                //打开打印机
                if (OpenPrinter(PrinterName, out hPrinter, ref defaults))
                {
                    try
                    {
                        //如果Form存在删除之
                        DeleteForm(hPrinter, PaperName);
                        //创建并初始化FORM_INFO_1
                        FormInfo1 formInfo = new FormInfo1();
                        formInfo.Flags = 0;
                        formInfo.pName = PaperName;
                        formInfo.Size.width = (int)(WidthInMm * 1000.0);
                        formInfo.Size.height = (int)(HeightInMm * 1000.0);
                        formInfo.ImageableArea.left = 0;
                        formInfo.ImageableArea.right = formInfo.Size.width;
                        formInfo.ImageableArea.top = 0;
                        formInfo.ImageableArea.bottom = formInfo.Size.height;
                        if (!AddForm(hPrinter, 1, ref formInfo))
                        {
                            StringBuilder strBuilder = new StringBuilder();
                            strBuilder.AppendFormat("向打印机 {1} 添加自定义纸张 {0} 失败!错误代号:{2}",
                             PaperName, PrinterName, GetLastError());
                            throw new ApplicationException(strBuilder.ToString());
                        }

//初始化
                        const int DM_OUT_BUFFER = 2;
                        const int DM_IN_BUFFER = 8;
                        structDevMode devMode = new structDevMode();
                        IntPtr hPrinterInfo, hDummy;
                        PRINTER_INFO_9 printerInfo;
                        printerInfo.pDevMode = IntPtr.Zero;
                        int iPrinterInfoSize, iDummyInt;
                        int iDevModeSize = DocumentProperties(IntPtr.Zero, hPrinter, PrinterName, IntPtr.Zero, IntPtr.Zero, 0);
                        if (iDevModeSize < 0)
                            throw new ApplicationException("无法取得DEVMODE结构的大小!");
                        //分配缓冲
                        IntPtr hDevMode = Marshal.AllocCoTaskMem(iDevModeSize + 100);
                        //获取DEV_MODE指针
                        int iRet = DocumentProperties(IntPtr.Zero, hPrinter, PrinterName, hDevMode, IntPtr.Zero, DM_OUT_BUFFER);
                        if (iRet < 0)
                            throw new ApplicationException("无法获得DEVMODE结构!");
                        //填充DEV_MODE
                        devMode = (structDevMode)Marshal.PtrToStructure(hDevMode, devMode.GetType());
                        devMode.dmFields = 0x10000;
                        //FORM名称
                        devMode.dmFormName = PaperName;
                        Marshal.StructureToPtr(devMode, hDevMode, true);
                        iRet = DocumentProperties(IntPtr.Zero, hPrinter, PrinterName,
                         printerInfo.pDevMode, printerInfo.pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER);
                        if (iRet < 0)
                            throw new ApplicationException("无法为打印机设定打印方向!");

GetPrinter(hPrinter, 9, IntPtr.Zero, 0, out iPrinterInfoSize);
                        if (iPrinterInfoSize == 0)
                            throw new ApplicationException("调用GetPrinter方法失败!");

hPrinterInfo = Marshal.AllocCoTaskMem(iPrinterInfoSize + 100);
                        bool bSuccess = GetPrinter(hPrinter, 9, hPrinterInfo, iPrinterInfoSize, out iDummyInt);
                        if (!bSuccess)
                            throw new ApplicationException("调用GetPrinter方法失败!");

printerInfo = (PRINTER_INFO_9)Marshal.PtrToStructure(hPrinterInfo, printerInfo.GetType());
                        printerInfo.pDevMode = hDevMode;
                        Marshal.StructureToPtr(printerInfo, hPrinterInfo, true);
                        bSuccess = SetPrinter(hPrinter, 9, hPrinterInfo, 0);
                        if (!bSuccess)
                            throw new Win32Exception(Marshal.GetLastWin32Error(), "调用SetPrinter方法失败,无法进行打印机设置!");

SendMessageTimeout(
                         new IntPtr(HWND_BROADCAST),
                         WM_SETTINGCHANGE,
                         IntPtr.Zero,
                         IntPtr.Zero,
                         PrinterHelper.SendMessageTimeoutFlags.SMTO_NORMAL,
                         1000,
                         out hDummy);
                    }
                    finally
                    {
                        ClosePrinter(hPrinter);
                    }
                }
                else
                {
                    StringBuilder strBuilder = new StringBuilder();
                    strBuilder.AppendFormat("无法打开打印机{0}, 错误代号: {1}",
                     PrinterName, GetLastError());
                    throw new ApplicationException(strBuilder.ToString());
                }
            }
            else
            {
                structDevMode pDevMode = new structDevMode();
                IntPtr hDC = CreateDC(null, PrinterName, null, ref pDevMode);
                if (hDC != IntPtr.Zero)
                {
                    const long DM_PAPERSIZE = 0x00000002L;
                    const long DM_PAPERLENGTH = 0x00000004L;
                    const long DM_PAPERWIDTH = 0x00000008L;
                    pDevMode.dmFields = (int)(DM_PAPERSIZE | DM_PAPERWIDTH | DM_PAPERLENGTH);
                    pDevMode.dmPaperSize = 256;
                    pDevMode.dmPaperWidth = (short)(WidthInMm * 1000.0);
                    pDevMode.dmPaperLength = (short)(HeightInMm * 1000.0);
                    ResetDC(hDC, ref pDevMode);
                    DeleteDC(hDC);
                }
            }
        }
        #endregion 指定的打印机设置以mm为单位的自定义纸张(Form)
        #region 获取本地打印机列表
        /// <summary>
        /// 获取本地打印机列表
        /// 可以通过制定参数获取网络打印机
        /// </summary>
        /// <returns>打印机列表</returns>
        public static ArrayList GetPrinterList()
        {
            ArrayList alRet = new ArrayList();
            PRINTER_INFO_2[] Info2 = EnumPrintersByFlag(PrinterEnumFlags.PRINTER_ENUM_LOCAL);
            for (int i = 0; i < Info2.Length; i++)
            {
                alRet.Add(Info2[i].pPrinterName);
            }
            return alRet;
        }
        #endregion 获取本地打印机列表

#region 获取本机的默认打印机名称
        /// <summary>
        /// 获取本机的默认打印机名称
        /// </summary>
        /// <returns>默认打印机名称</returns>
        public static string GetDeaultPrinterName()
        {
            StringBuilder dp = new StringBuilder(256);
            int size = dp.Capacity;
            if (GetDefaultPrinter(dp, ref size))
            {
                return dp.ToString();
            }
            else
            {
                return string.Empty;
            }
        }
        #endregion 获取本机的默认打印机名称
        #region 设置默认打印机
        /// <summary>
        /// 设置默认打印机
        /// </summary>
        /// <param name="PrinterName">可用的打印机名称</param>
        public static void SetPrinterToDefault(string PrinterName)
        {
            SetDefaultPrinter(PrinterName);
        }
        #endregion 设置默认打印机
        #region 判断打印机是否在系统可用的打印机列表中
        /// <summary>
        /// 判断打印机是否在系统可用的打印机列表中
        /// </summary>
        /// <param name="printerName"></param>
        /// <returns></returns>
        public static bool PrinterInList(string printerName)
        {
            bool bolRet = false;

System.Collections.ArrayList alPrinters = GetPrinterList();

for (int i = 0; i < alPrinters.Count; i++)
            {
                if (printerName == alPrinters[i].ToString())
                {
                    bolRet = true;
                    break;
                }
            }

alPrinters.Clear();
            alPrinters = null;

return bolRet;
        }
        #endregion 判断打印机是否在系统可用的打印机列表中
        #region 判断表单是否在指定的打印机所支持的纸张列表中
        /// <summary>
        /// 判断表单是否在指定的打印机所支持的纸张列表中,表单就是我们平常所说的纸张
        /// </summary>
        /// <param name="printerName"></param>
        /// <param name="paperName"></param>
        /// <returns></returns>
        public static bool FormInPrinter(string printerName, string paperName)
        {
            bool bolRet = false;
            System.Drawing.Printing.PrintDocument pd = new System.Drawing.Printing.PrintDocument();
            pd.PrinterSettings.PrinterName = printerName;
            foreach (PaperSize ps in pd.PrinterSettings.PaperSizes)
            {
                if (ps.PaperName == paperName)
                {
                    bolRet = true;
                    break;
                }
            }
            pd.Dispose();
            return bolRet;
        }
        #endregion 判断表单是否在指定的打印机所支持的纸张列表中
        #region 判断指定纸张的宽度和高度和与打印内容指定的宽度和高度是否匹配
        /// <summary>
        /// 判断指定纸张的宽度和高度和与打印内容指定的宽度和高度是否匹配
        /// </summary>
        /// <param name="PrinterName">打印机名称</param>
        /// <param name="FormName">表单名称</param>
        /// <param name="Width">宽度</param>
        /// <param name="Height">高度</param>
        /// <returns></returns>
        public static bool FormSameSize(string PrinterName, string FormName, decimal Width, decimal Height)
        {
            bool bolRet = false;
            System.Drawing.Printing.PrintDocument pd = new System.Drawing.Printing.PrintDocument();
            pd.PrinterSettings.PrinterName = PrinterName;
            foreach (PaperSize ps in pd.PrinterSettings.PaperSizes)
            {
                if (ps.PaperName == FormName)
                {
                    decimal decWidth = FromInchToCM(System.Convert.ToDecimal(ps.Width));
                    decimal decHeight = FromInchToCM(System.Convert.ToDecimal(ps.Height));
                    //只要整数位相同即认为是同一纸张,毕竟inch到cm的转换并不能整除
                    if (Math.Round(decWidth, 0) == Math.Round(Width, 0) && Math.Round(decHeight, 0) == Math.Round(Height, 0))
                        bolRet = true;
                    break;
                }
            }
            pd.Dispose();
            return bolRet;
        }
        #endregion 判断指定纸张的宽度和高度和与打印内容指定的宽度和高度是否匹配
        #region 英寸到厘米的转换
        
        /// <summary>
        /// 英寸到厘米的转换
        /// /* = = = = = = = = = = = = = = = = *\
        /// | 换算一下计量单位,将其换算成厘米  |
        /// |    厘米     像素     英寸         |
        /// |     1        38     0.395         |
        /// |   0.026       1      0.01         |
        /// |    2.54      96        1          |
        /// \* = = = = = = = = = = = = = = = = */
        /// </summary>
        /// <param name="inch">英寸数</param>
        /// <returns>厘米数,两位小数</returns>
        public static decimal FromInchToCM(decimal inch)
        {
            return Math.Round((System.Convert.ToDecimal((inch / 100)) * System.Convert.ToDecimal(2.5400)), 2);
        }
        #endregion 英寸到厘米的转换

/// <summary>
        ///
        /// </summary>
        /// <param name="szPrinter"></param>
        /// <param name="hPrinter"></param>
        /// <param name="pd"></param>
        /// <returns></returns>
        [DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd);

//[DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        //public static extern bool ClosePrinter(IntPtr hPrinter);

/// <summary>
        ///
        /// </summary>
        /// <param name="hPrinter"></param>
        /// <param name="level"></param>
        /// <param name="di"></param>
        /// <returns></returns>
        [DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool StartDocPrinter(IntPtr hPrinter, Int32 level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);

/// <summary>
        ///
        /// </summary>
        /// <param name="hPrinter"></param>
        /// <returns></returns>
        [DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool EndDocPrinter(IntPtr hPrinter);

/// <summary>
        ///
        /// </summary>
        /// <param name="hPrinter"></param>
        /// <returns></returns>
        [DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool StartPagePrinter(IntPtr hPrinter);

/// <summary>
        ///
        /// </summary>
        /// <param name="hPrinter"></param>
        /// <returns></returns>
        [DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool EndPagePrinter(IntPtr hPrinter);

/// <summary>
        ///
        /// </summary>
        /// <param name="hPrinter"></param>
        /// <param name="pBytes"></param>
        /// <param name="dwCount"></param>
        /// <param name="dwWritten"></param>
        /// <returns></returns>
        [DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, Int32 dwCount, out Int32 dwWritten);

/// <summary>
        /// 该方法把非托管内存中的字节数组发送到打印机的打印队列
        /// </summary>
        /// <param name="szPrinterName">打印机名称</param>
        /// <param name="pBytes">非托管内存指针</param>
        /// <param name="dwCount">字节数</param>
        /// <returns>成功返回true,失败时为false</returns>
        public static bool SendBytesToPrinter(string szPrinterName, IntPtr pBytes, Int32 dwCount)
        {
            Int32 dwError = 0, dwWritten = 0;
            IntPtr hPrinter = new IntPtr(0);
            DOCINFOA di = new DOCINFOA();
            bool bSuccess = false;
            di.pDocName = "My C#.NET RAW Document";
            di.pDataType = "RAW";
            try
            {
                // 打开打印机
                if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
                {
                    // 启动文档打印
                    if (StartDocPrinter(hPrinter, 1, di))
                    {
                        // 开始打印
                        if (StartPagePrinter(hPrinter))
                        {
                            // 向打印机输出字节  
                            bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
                            EndPagePrinter(hPrinter);
                        }
                        EndDocPrinter(hPrinter);
                    }
                    ClosePrinter(hPrinter);
                }
                if (!bSuccess)
                {
                    dwError = Marshal.GetLastWin32Error();
                }
            }
            catch (Win32Exception ex)
            {
                WriteLog(ex.Message);
                bSuccess = false;
            }
            return bSuccess;
        }

/// <summary>
        /// 发送文件到打印机方法
        /// </summary>
        /// <param name="szPrinterName">打印机名称</param>
        /// <param name="szFileName">打印文件的路径</param>
        /// <returns></returns>
        public static bool SendFileToPrinter(string szPrinterName, string szFileName)
        {
            bool bSuccess = false;
            try
            {
                // 打开文件  
                FileStream fs = new FileStream(szFileName, FileMode.Open);
                // 将文件内容读作二进制
                BinaryReader br = new BinaryReader(fs);
                // 定义字节数组
                Byte[] bytes = new Byte[fs.Length];
                // 非托管指针  
                IntPtr pUnmanagedBytes = new IntPtr(0);
                int nLength;
                nLength = Convert.ToInt32(fs.Length);
                // 读取文件内容到字节数组
                bytes = br.ReadBytes(nLength);
                // 为这些字节分配一些非托管内存
                pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength);
                // 将托管字节数组复制到非托管内存指针
                Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength);
                // 将非托管字节发送到打印机
                bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength);
                // 释放先前分配的非托管内存
                Marshal.FreeCoTaskMem(pUnmanagedBytes);
                fs.Close();
                fs.Dispose();
            }
            catch (Win32Exception ex)
            {
                WriteLog(ex.Message);
                bSuccess = false;
            }
            return bSuccess;
        }

/// <summary>
        /// 将字符串发送到打印机方法
        /// </summary>
        /// <param name="szPrinterName">打印机名称</param>
        /// <param name="szString">打印的字符串</param>
        /// <returns></returns>
        public static bool SendStringToPrinter(string szPrinterName, string szString)
        {
            bool flag = false;
            try
            {
                IntPtr pBytes;
                Int32 dwCount;
                // 获取字符串长度  
                dwCount = szString.Length;
                // 将字符串复制到非托管 COM 任务分配的内存非托管内存块,并转换为 ANSI 文本
                pBytes = Marshal.StringToCoTaskMemAnsi(szString);
                // 将已转换的 ANSI 字符串发送到打印机
                flag = SendBytesToPrinter(szPrinterName, pBytes, dwCount);
                // 释放先前分配的非托管内存
                Marshal.FreeCoTaskMem(pBytes);
            }
            catch (Win32Exception ex)
            {
                WriteLog(ex.Message);
                flag = false;
            }
            return flag;
        }

/// <summary>
        /// 写入日志方法
        /// </summary>
        /// <param name="msg">记录信息</param>
        public static void WriteLog(string msg)
        {
            string str = string.Empty;
            string path = AppDomain.CurrentDomain.BaseDirectory + "log\\" + DateTime.Now.ToString("yyyy-MM-dd") + ".txt";
            FileStream filestream = new FileStream(path, FileMode.OpenOrCreate);
            str += "************" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "************\r\n";
            str += msg;
            str += "************" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "************\r\n";
            FileStream fs = new FileStream(path, FileMode.Append);
            StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.Default);
            sw.WriteLine(str);
            sw.Flush();
            sw.Close();
            sw.Dispose();
            fs.Close();
            fs.Dispose();
        }
    }

/// <summary>
    ///
    /// </summary>
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public class DOCINFOA
    {
        /// <summary>
        ///
        /// </summary>
        [MarshalAs(UnmanagedType.LPStr)]
        public string pDocName;

/// <summary>
        ///
        /// </summary>
        [MarshalAs(UnmanagedType.LPStr)]
        public string pOutputFile;

/// <summary>
        ///
        /// </summary>
        [MarshalAs(UnmanagedType.LPStr)]
        public string pDataType;
    }
}

C#&.Net干货分享- 构建PrinterHelper直接调用打印机相关操作的更多相关文章

  1. C#&.Net干货分享- 构建Spire-Office相关Helper操作Word、Excel、PDF等

    先下载好如下的组件: 直接使用完整源码分享: namespace Frame.Office{    /// <summary>    /// Spire_WordHelper    /// ...

  2. C#&.Net干货分享-构建后台自动定时任务的源码

    1.创建一个自动处理中心任务参数的类,直接源码: namespace Frame.AutoProcess{    /// <summary>    /// 委托(用于异步处理任务)    ...

  3. C#&.Net干货分享-构建Aocr_ImageHelper读取图片文字做解析

    直接源码,就是这么干脆... namespace Frame.Image{    /// <summary>    ///     /// </summary>    publ ...

  4. 32位汇编第四讲,干货分享,汇编注入的实现,以及快速定位调用API的数量(OD查看)

    32位汇编第四讲,干货分享,汇编注入的实现,以及快速定位调用API的数量(OD查看) 昨天,大家可能都看了代码了,不知道昨天有没有在汇编代码的基础上,实现注入计算器. 如果没有,今天则会讲解,不过建议 ...

  5. 最强最全干货分享:Android开发书籍、教程、工具等

    最全干货分享,本文收集整理了Android开发所需的书籍.教程.工具.资讯和周刊各种资源,它们能让你在Android开发之旅的各个阶段都受益. 入门<Learning Android(中文版)& ...

  6. 干货分享:SQLSERVER使用裸设备

    干货分享:SQLSERVER使用裸设备 这篇文章也适合ORACLE DBA和MYSQL DBA 阅读 裸设备适用于Linux和Windows 在ORACLE和MYSQL里也是支持裸设备的!! 介绍 大 ...

  7. 【腾讯Bugly干货分享】浅谈Android自定义锁屏页的发车姿势

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57875330c9da73584b025873 一.为什么需要自定义锁屏页 锁屏 ...

  8. 逆向实用干货分享,Hook技术第一讲,之Hook Windows API

    逆向实用干货分享,Hook技术第一讲,之Hook Windows API 作者:IBinary出处:http://www.cnblogs.com/iBinary/版权所有,欢迎保留原文链接进行转载:) ...

  9. 逆向实用干货分享,Hook技术第二讲,之虚表HOOK

    逆向实用干货分享,Hook技术第二讲,之虚表HOOK 正好昨天讲到认识C++中虚表指针,以及虚表位置在反汇编中的表达方式,这里就说一下我们的新技术,虚表HOOK 昨天的博客链接: http://www ...

随机推荐

  1. Pandas学习(一)——数据的导入

    欢迎加入python学习交流群 667279387 学习笔记汇总 Pandas学习(一)–数据的导入 pandas学习(二)–双色球数据分析 pandas学习(三)–NAB球员薪资分析 pandas学 ...

  2. numpy sum axis详解

    axis 先看懂numpy.argmax的含义.那么numpy.sum就非常好理解. 看一维的例子. import numpy as np a = np.array([1, 5, 5, 2]) pri ...

  3. 插入排序 C&&C++

    (blog主要用于展示算法流程) 插入排序算法:通过对未排序的数据逐个插入合适的位置而完成排序工作       流程: (1)先对数组前两个数据进行从小到大排序 (2)将第三个数据与前两个数据比较,将 ...

  4. Codeforces Round #590 (Div. 3)

    A. Equalize Prices Again 题目链接:https://codeforces.com/contest/1234/problem/A 题意:给你 n 个数 , 你需要改变这些数使得这 ...

  5. android 7.0+、8.0+应用中点击拍照崩溃的解决办法

    在开发中,项目里面明明已经添加过拍照或者读取相册的权限,但是在点击拍照或者打开相册的时候应用会崩溃,报一下错误: Caused by: android.os.FileUriExposedExcepti ...

  6. 语句知识总结(js)

    函数声明语句和函数定义表达式有什么不同 首先看一下函数声明语句和函数定义表达式的例子,表达式会返回一个值,而语句就是js中的一整句,下面例子中第6行是函数声明语句,第10行是函数定义表达式. f(); ...

  7. python网络编程socketserver模块(实现TCP客户端/服务器)

    摘录python核心编程 socketserver(python3.x版本重新命名)是标准库中的网络编程的高级模块.通过将创建网络客户端和服务器所必须的代码封装起来,简化了模板,为你提供了各种各样的类 ...

  8. PlayJava SSM框架简介

    SSM框架 SSM是Spring + Spring MVC + MyBatis的缩写,是一个继SSH之后目前比较主流的JavaEE框架,适用于搭建各种企业级应用系统. Spring Spring是一个 ...

  9. Git很麻烦?只要掌握这几个命令,轻松将代码提交远程仓库

    在上一章节,跟大家介绍了拉取代码的操作,简单暴力.这一章节要介绍的是如何将现有的项目,直接提交到仓库. 现在,如果大家有一个项目要提交到GitHub仓库,安装上一张的方法,需要先在GitHub上建一个 ...

  10. Spring Boot Web开发与thymeleaf模板引擎

    简介: 使用Springboot应用,选中需要的模块, Spring已经默认将场景配置好了,只需在配置文件中少量配置就可以运行起来 自己编写业务代码 自动配置原理 这个场景Springboot帮我们配 ...