欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C#之Windows自帶打印功能的實(shí)現(xiàn)

 更新時(shí)間:2023年06月26日 10:15:43   作者:王嘯tr1912  
這篇文章主要介紹了C#之Windows自帶打印功能的實(shí)現(xiàn)方式,具有很好的價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

接著上回說(shuō),在使用打印機(jī)自帶的SDK開(kāi)發(fā)失利只后,經(jīng)過(guò)一系列的實(shí)驗(yàn),發(fā)現(xiàn),這個(gè)打印機(jī)可以直接用我安裝好的驅(qū)動(dòng)直接進(jìn)行打印操作,用word直接調(diào)整好字體之后打印是完全沒(méi)有問(wèn)題的,所以,推測(cè),應(yīng)該可以直接調(diào)用人家封裝好的一些驅(qū)動(dòng)進(jìn)行打印,但是要怎么連接這些驅(qū)動(dòng)呢?

一、打印控件

首先我們要提到的就是在C#中的一個(gè)關(guān)于打印的控件了,叫:PrintDocument,說(shuō)他是一個(gè)控件,其實(shí)也就是一個(gè)關(guān)于windows打印的屬性和代碼的集合而已,但是結(jié)合著windows自帶的一些對(duì)話框窗體,我們可以輕而易舉的做一個(gè)打印的小程序。

我們要做的是,首先建立一個(gè)窗體,然后從工具箱中找到PrintDocument這個(gè)控件,然后添加上就可以了,可以看到控件的屬性是這樣的:

并沒(méi)有什么特殊的地方,但是在方法里面卻有一個(gè)很重要的方法,那就是他的printPage這個(gè)方法,這個(gè)就是每次觸發(fā)這個(gè)控件的打印的內(nèi)容核心,先貼上如下代碼:

private void pd1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
        {
            Graphics g = e.Graphics; //獲得繪圖對(duì)象
            float linesPerPage = 0; //頁(yè)面的行號(hào)
            float yPosition = 0;   //繪制字符串的縱向位置
            int count = 0; //行計(jì)數(shù)器
            float leftMargin = 1; //左邊距
            float topMargin = 1; //上邊距
            string line = ""; //行字符串
            Font printFont = this.textBox1.Font; //當(dāng)前的打印字體
            SolidBrush myBrush = new SolidBrush(Color.Black);//刷子
            linesPerPage = e.MarginBounds.Height / printFont.GetHeight(g);//每頁(yè)可打印的行數(shù)
            //逐行的循環(huán)打印一頁(yè)
            while (count < linesPerPage && ((line = lineReader.ReadLine()) != null))
            {
                yPosition = topMargin + (count * printFont.GetHeight(g));
                g.DrawString(line, printFont, myBrush, leftMargin, yPosition, new StringFormat());
                count++;
            }
            // 注意:使用本段代碼前,要在該窗體的類中定義lineReader對(duì)象:
            //       StringReader lineReader = null;
            //如果本頁(yè)打印完成而line不為空,說(shuō)明還有沒(méi)完成的頁(yè)面,這將觸發(fā)下一次的打印事件。在下一次的打印中l(wèi)ineReader會(huì)
            //自動(dòng)讀取上次沒(méi)有打印完的內(nèi)容,因?yàn)閘ineReader是這個(gè)打印方法外的類的成員,它可以記錄當(dāng)前讀取的位置
            if (line != null)
                e.HasMorePages = true;
            else
            {
                e.HasMorePages = false;
                // 重新初始化lineReader對(duì)象,不然使用打印預(yù)覽中的打印按鈕打印出來(lái)是空白頁(yè)
                lineReader = new StringReader(textBox1.Text); // textBox是你要打印的文本框的內(nèi)容
            }
        }

這里需要注意的是,使用了lineReader這個(gè)類的對(duì)象,這個(gè)對(duì)象的特點(diǎn)就是可以把對(duì)象中賦值的字符串按照行(以\r\n為準(zhǔn)的換行)來(lái)進(jìn)行字符串的獲取,上面代碼中的line就是指的獲得的一行的數(shù)據(jù)。

我們用system.draw的Graphics里面的繪圖對(duì)象來(lái)進(jìn)行基本的字符繪圖,最后把繪圖對(duì)象打印到我們紙上,就是這個(gè)打印里面的內(nèi)容。

所以,我們這個(gè)里面需要引入的一個(gè)引用就是using System.Drawing.Printing;   這樣整個(gè)控件加代碼就可以運(yùn)行了,說(shuō)明一下,這個(gè)打印的調(diào)用需要觸發(fā),使用的是如下代碼:

lineReader = new StringReader(stb.ToString());   // 獲取要打印的字符串
pd1.Print();      //執(zhí)行打印方法

另外說(shuō)明一下,這里執(zhí)行的時(shí)候,有一些輔助設(shè)置,比如打印預(yù)覽,打印機(jī)使用的默認(rèn)的,還有頁(yè)面的配置等都是有專門的對(duì)話框,我把他們都放在了菜單里面,

如圖:

下面我們來(lái)說(shuō)一下他們的實(shí)現(xiàn),其實(shí)很是簡(jiǎn)單:

打印設(shè)置:

private void FileMenuItem_PrintSet_Click(object sender, EventArgs e)
{
   PrintDialog printDialog = new PrintDialog();
   printDialog.Document = pd1;
   printDialog.ShowDialog();
}

頁(yè)面設(shè)置:

private void FileMenuItem_PageSet_Click(object sender, EventArgs e)
{
     PageSetupDialog pageSetupDialog = new PageSetupDialog();
     pageSetupDialog.Document = pd1;
     pageSetupDialog.ShowDialog();
}

打印預(yù)覽:

private void FileMenuItem_PrintView_Click(object sender, EventArgs e)
{
    PrintPreviewDialog printPreviewDialog = new PrintPreviewDialog();
    printPreviewDialog.Document = pd1;
    lineReader = new StringReader(stb.ToString());
    try
    {
        printPreviewDialog.ShowDialog();
    }
    catch(Exception excep)
    {
        MessageBox.Show(excep.Message, "打印出錯(cuò)", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

 

這些頁(yè)面里面的設(shè)置在選擇保存的時(shí)候會(huì)自動(dòng)存儲(chǔ)到Graphic對(duì)象當(dāng)中,因此,可以配置之后使用。

二、系統(tǒng)API接口

既然有系統(tǒng)定制的控件,那么系統(tǒng)的接入API肯定也少不了,不過(guò),我目前從網(wǎng)絡(luò)上找到的只有一小部分而已,并且都是一些獲取配置,設(shè)置默認(rèn)等一些列的代碼,在此分享給大家

using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Security;
using System.ComponentModel;
using System.IO;
namespace WindowsFormsApplication1
{
    public class PrinterHelper
    {
        private PrinterHelper(){ }  
        #region API聲明
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        internal struct structPrinterDefaults
        {
            [MarshalAs(UnmanagedType.LPTStr)]
            public String pDatatype;
            public IntPtr pDevMode;
            [MarshalAs(UnmanagedType.I4)]
            public int DesiredAccess;
        };
        [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);
        [DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true,CharSet = CharSet.Unicode, ExactSpelling = false,CallingConvention = CallingConvention.StdCall), SuppressUnmanagedCodeSecurityAttribute()]
        internal static extern bool ClosePrinter(IntPtr phPrinter);
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        internal struct structSize
        {
            public Int32 width;
            public Int32 height;
        }
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        internal struct structRect
        {
            public Int32 left;
            public Int32 top;
            public Int32 right;
            public Int32 bottom;
        }
        [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;
        };
        [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;
        }
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        internal struct PRINTER_INFO_9
        {
            public IntPtr pDevMode;
        }
        [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);
        [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);
        [DllImport("kernel32.dll", EntryPoint = "GetLastError", SetLastError = false,ExactSpelling = true, CallingConvention = CallingConvention.StdCall),SuppressUnmanagedCodeSecurityAttribute()]
        internal static extern Int32 GetLastError();
        [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);
        [DllImport("GDI32.dll", EntryPoint = "DeleteDC", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = false,
                    CallingConvention = CallingConvention.StdCall),SuppressUnmanagedCodeSecurityAttribute()]
        internal static extern bool DeleteDC(IntPtr hDC);
        [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);
        [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);
        [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);
        [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;
        [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);
        //EnumPrinters用到的函數(shù)和結(jié)構(gòu)體
        [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);
        [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;
        }
        [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
        }
        //打印機(jī)狀態(tài)
        [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
        }
        //GetDefaultPrinter用到的API函數(shù)說(shuō)明
        [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
        internal static extern bool GetDefaultPrinter(StringBuilder pszBuffer, ref int size);
        //SetDefaultPrinter用到的API函數(shù)聲明
        [DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
        internal static extern bool SetDefaultPrinter(string Name);
        //EnumFormsA用到的函數(shù)聲明,應(yīng)該和EnumPrinters類似
        [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聲明
        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;
        }
        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 獲取當(dāng)前指定打印機(jī)的狀態(tài)
        /// </summary>
        /// 獲取當(dāng)前指定打印機(jī)的狀態(tài)
        /// </summary>
        /// <param name="PrinterName">打印機(jī)名稱</param>
        /// <returns>打印機(jī)狀態(tài)描述</returns>
        public static string GetPrinterStatus(string PrinterName)
        {
            int intValue = GetPrinterStatusInt(PrinterName);
            string strRet = string.Empty;
            switch (intValue)
            {
                case 0:
                    strRet = "準(zhǔn)備就緒(Ready)";
                    break;
                case 0x00000200:
                    strRet = "忙(Busy)";
                    break;
                case 0x00400000:
                    strRet = "門被打開(kāi)(Printer Door Open)";
                    break;
                case 0x00000002:
                    strRet = "錯(cuò)誤(Printer Error)";
                    break;
                case 0x0008000:
                    strRet = "正在初始化(Initializing)";
                    break;
                case 0x00000100:
                    strRet = "正在輸入或輸出(I/O Active)";
                    break;
                case 0x00000020:
                    strRet = "手工送紙(Manual Feed)";
                    break;
                case 0x00040000:
                    strRet = "無(wú)墨粉(No Toner)";
                    break;
                case 0x00001000:
                    strRet = "不可用(Not Available)";
                    break;
                case 0x00000080:
                    strRet = "脫機(jī)(Off Line)";
                    break;
                case 0x00200000:
                    strRet = "內(nèi)存溢出(Out of Memory)";
                    break;
                case 0x00000800:
                    strRet = "輸出口已滿(Output Bin Full)";
                    break;
                case 0x00080000:
                    strRet = "當(dāng)前頁(yè)無(wú)法打?。≒age Punt)";
                    break;
                case 0x00000008:
                    strRet = "塞紙(Paper Jam)";
                    break;
                case 0x00000010:
                    strRet = "打印紙用完(Paper Out)";
                    break;
                case 0x00000040:
                    strRet = "紙張問(wèn)題(Page Problem)";
                    break;
                case 0x00000001:
                    strRet = "暫停(Paused)";
                    break;
                case 0x00000004:
                    strRet = "正在刪除(Pending Deletion)";
                    break;
                case 0x00000400:
                    strRet = "正在打?。≒rinting)";
                    break;
                case 0x00004000:
                    strRet = "正在處理(Processing)";
                    break;
                case 0x00020000:
                    strRet = "墨粉不足(Toner Low)";
                    break;
                case 0x00100000:
                    strRet = "需要用戶干預(yù)(User Intervention)";
                    break;
                case 0x20000000:
                    strRet = "等待(Waiting)";
                    break;
                case 0x00010000:
                    strRet = "正在準(zhǔn)備(Warming Up)";
                    break;
                default:
                    strRet = "未知狀態(tài)(Unknown Status)";
                    break;
            }
            return strRet;
        }
        #endregion 獲取當(dāng)前指定打印機(jī)的狀態(tài)
        #region 刪除已經(jīng)存在的自定義紙張
        /**/
        /// <summary>
        /// 刪除已經(jīng)存在的自定義紙張
        /// </summary>
        /// <param name="PrinterName">打印機(jī)名稱</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;
            //打開(kāi)打印機(jī)
            if (OpenPrinter(PrinterName, out hPrinter, ref defaults))
            {
                try
                {
                    DeleteForm(hPrinter, PaperName);
                    ClosePrinter(hPrinter);
                }
                catch
                {
                }
            }
        }
        #endregion 刪除已經(jīng)存在的自定義紙張
        #region 指定的打印機(jī)設(shè)置以mm為單位的自定義紙張(Form)
        /**/
        /// <summary>
        /// 指定的打印機(jī)設(shè)置以mm為單位的自定義紙張(Form)
        /// </summary>
        /// <param name="PrinterName">打印機(jī)名稱</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;
                //打開(kāi)打印機(jī)
                if (OpenPrinter(PrinterName, out hPrinter, ref defaults))
                {
                    try
                    {
                        //如果Form存在刪除之
                        DeleteForm(hPrinter, PaperName);
                        //創(chuàng)建并初始化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("向打印機(jī) {1} 添加自定義紙張 {0} 失?。″e(cuò)誤代號(hào):{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("無(wú)法取得DEVMODE結(jié)構(gòu)的大??!");
                        //分配緩沖
                        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("無(wú)法獲得DEVMODE結(jié)構(gòu)!");
                        //填充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("無(wú)法為打印機(jī)設(shè)定打印方向!");
                        GetPrinter(hPrinter, 9, IntPtr.Zero, 0, out iPrinterInfoSize);
                        if (iPrinterInfoSize == 0)
                            throw new ApplicationException("調(diào)用GetPrinter方法失敗!");
                        hPrinterInfo = Marshal.AllocCoTaskMem(iPrinterInfoSize + 100);
                        bool bSuccess = GetPrinter(hPrinter, 9, hPrinterInfo, iPrinterInfoSize, out iDummyInt);
                        if (!bSuccess)
                            throw new ApplicationException("調(diào)用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(), "調(diào)用SetPrinter方法失敗,無(wú)法進(jìn)行打印機(jī)設(shè)置!");
                        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("無(wú)法打開(kāi)打印機(jī){0}, 錯(cuò)誤代號(hào): {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 指定的打印機(jī)設(shè)置以mm為單位的自定義紙張(Form)
        #region 獲取本地打印機(jī)列表
        /**/
        /// <summary>
        /// 獲取本地打印機(jī)列表
        /// 可以通過(guò)制定參數(shù)獲取網(wǎng)絡(luò)打印機(jī)
        /// </summary>
        /// <returns>打印機(jī)列表</returns>
        public static System.Collections.ArrayList GetPrinterList()
        {
            System.Collections.ArrayList alRet = new System.Collections.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 獲取本地打印機(jī)列表
        #region 獲取本機(jī)的默認(rèn)打印機(jī)名稱
        /**/
        /// <summary>
        /// 獲取本機(jī)的默認(rèn)打印機(jī)名稱
        /// </summary>
        /// <returns>默認(rèn)打印機(jī)名稱</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 獲取本機(jī)的默認(rèn)打印機(jī)名稱
        #region 設(shè)置默認(rèn)打印機(jī)
        /**/
        /// <summary>
        /// 設(shè)置默認(rèn)打印機(jī)
        /// </summary>
        /// <param name="PrinterName">可用的打印機(jī)名稱</param>
        public static void SetPrinterToDefault(string PrinterName)
        {
            SetDefaultPrinter(PrinterName);
        }
        #endregion 設(shè)置默認(rèn)打印機(jī)
        #region 判斷打印機(jī)是否在系統(tǒng)可用的打印機(jī)列表中
        /**/
        / <summary>
        / 判斷打印機(jī)是否在系統(tǒng)可用的打印機(jī)列表中
        / </summary>
        / <param name="PrinterName">打印機(jī)名稱</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 判斷打印機(jī)是否在系統(tǒng)可用的打印機(jī)列表中
        #region 判斷表單是否在指定的打印機(jī)所支持的紙張列表中
        /**/
        / <summary>
        / 判斷表單是否在指定的打印機(jī)所支持的紙張列表中,表單就是我們平常所說(shuō)的紙張
        / </summary>
        / <param name="PrinterName">打印機(jī)名稱</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 (System.Drawing.Printing.PaperSize ps in pd.PrinterSettings.PaperSizes)
            {
                if (ps.PaperName == PaperName)
                {
                    bolRet = true;
                    break;
                }
            }
            pd.Dispose();
            return bolRet;
        }
        #endregion 判斷表單是否在指定的打印機(jī)所支持的紙張列表中
        #region 判斷指定紙張的寬度和高度和與打印內(nèi)容指定的寬度和高度是否匹配
        /**/
        /// <summary>
        /// 判斷指定紙張的寬度和高度和與打印內(nèi)容指定的寬度和高度是否匹配
        /// </summary>
        /// <param name="PrinterName">打印機(jī)名稱</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 (System.Drawing.Printing.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));
                    //只要整數(shù)位相同即認(rèn)為是同一紙張,畢竟inch到cm的轉(zhuǎn)換并不能整除
                    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 判斷指定紙張的寬度和高度和與打印內(nèi)容指定的寬度和高度是否匹配
        #region 英寸到厘米的轉(zhuǎn)換
        /**/
        /// <summary>
        /// 英寸到厘米的轉(zhuǎn)換
        /// /* = = = = = = = = = = = = = = = = *\
        /// | 換算一下計(jì)量單位,將其換算成厘米  |
        /// |    厘米     像素     英寸         |
        /// |     1        38     0.395         |
        /// |   0.026       1      0.01         |
        /// |    2.54      96        1          |
        /// \* = = = = = = = = = = = = = = = = */
        /// </summary>
        /// <param name="inch">英寸數(shù)</param>
        /// <returns>厘米數(shù),兩位小數(shù)</returns>
        ///
        public static decimal FromInchToCM(decimal inch)
        {
            return Math.Round((System.Convert.ToDecimal((inch / 100)) * System.Convert.ToDecimal(2.5400)), 2);
        }
        #endregion 英寸到厘米的轉(zhuǎn)換
        [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);
        [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);
        [DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool EndDocPrinter(IntPtr hPrinter);
        [DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool StartPagePrinter(IntPtr hPrinter);
        [DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
        public static extern bool EndPagePrinter(IntPtr hPrinter);
        [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>
        /// 該方法把非托管內(nèi)存中的字節(jié)數(shù)組發(fā)送到打印機(jī)的打印隊(duì)列
        /// </summary>
        /// <param name="szPrinterName">打印機(jī)名稱</param>
        /// <param name="pBytes">非托管內(nèi)存指針</param>
        /// <param name="dwCount">字節(jié)數(shù)</param>
        /// <returns>成功返回true,失敗時(shí)為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
            {
                // 打開(kāi)打印機(jī)
                if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
                {
                    // 啟動(dòng)文檔打印
                    if (StartDocPrinter(hPrinter, 1, di))
                    {
                        // 開(kāi)始打印
                        if (StartPagePrinter(hPrinter))
                        {
                            // 向打印機(jī)輸出字節(jié)  
                            bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
                            EndPagePrinter(hPrinter);
                        }
                        EndDocPrinter(hPrinter);
                    }
                    ClosePrinter(hPrinter);
                }
                if (bSuccess == false)
                {
                    dwError = Marshal.GetLastWin32Error();
                }
            }
            catch (Win32Exception ex)
            {
                WriteLog(ex.Message);
                bSuccess = false;
            }
            return bSuccess;
        }
        /// <summary>
        /// 發(fā)送文件到打印機(jī)方法
        /// </summary>
        /// <param name="szPrinterName">打印機(jī)名稱</param>
        /// <param name="szFileName">打印文件的路徑</param>
        /// <returns></returns>
        public static bool SendFileToPrinter(string szPrinterName, string szFileName)
        {
            bool bSuccess = false;
            try
            {
                // 打開(kāi)文件  
                FileStream fs = new FileStream(szFileName, FileMode.Open);
                // 將文件內(nèi)容讀作二進(jìn)制
                BinaryReader br = new BinaryReader(fs);
                // 定義字節(jié)數(shù)組
                Byte[] bytes = new Byte[fs.Length];
                // 非托管指針  
                IntPtr pUnmanagedBytes = new IntPtr(0);
                int nLength;
                nLength = Convert.ToInt32(fs.Length);
                // 讀取文件內(nèi)容到字節(jié)數(shù)組
                bytes = br.ReadBytes(nLength);
                // 為這些字節(jié)分配一些非托管內(nèi)存
                pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength);
                // 將托管字節(jié)數(shù)組復(fù)制到非托管內(nèi)存指針
                Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength);
                // 將非托管字節(jié)發(fā)送到打印機(jī)
                bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength);
                // 釋放先前分配的非托管內(nèi)存
                Marshal.FreeCoTaskMem(pUnmanagedBytes);
                fs.Close();
                fs.Dispose();
            }
            catch (Win32Exception ex)
            {
                WriteLog(ex.Message);
                bSuccess = false;
            }
            return bSuccess;
        }
        /// <summary>
        /// 將字符串發(fā)送到打印機(jī)方法
        /// </summary>
        /// <param name="szPrinterName">打印機(jī)名稱</param>
        /// <param name="szString">打印的字符串</param>
        /// <returns></returns>
        public static bool SendStringToPrinter(string szPrinterName, string szString)
        {
            bool flag = false;
            try
            {
                IntPtr pBytes;
                Int32 dwCount;
                // 獲取字符串長(zhǎng)度  
                dwCount = szString.Length;
                // 將字符串復(fù)制到非托管 COM 任務(wù)分配的內(nèi)存非托管內(nèi)存塊,并轉(zhuǎn)換為 ANSI 文本
                pBytes = Marshal.StringToCoTaskMemAnsi(szString);
                // 將已轉(zhuǎn)換的 ANSI 字符串發(fā)送到打印機(jī)
                flag = SendBytesToPrinter(szPrinterName, pBytes, dwCount);
                // 釋放先前分配的非托管內(nèi)存
                Marshal.FreeCoTaskMem(pBytes);
            }
            catch (Win32Exception ex)
            {
                WriteLog(ex.Message);
                flag = false;
            }
            return flag;
        }
        /// <summary>
        /// 寫(xiě)入日志方法
        /// </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();
        }
    }
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public class DOCINFOA
    {
        [MarshalAs(UnmanagedType.LPStr)]
        public string pDocName;
        [MarshalAs(UnmanagedType.LPStr)]
        public string pOutputFile;
        [MarshalAs(UnmanagedType.LPStr)]
        public string pDataType;
    }
}

我們可以看到,這些函數(shù)都是調(diào)用的winspool.drv 這個(gè)windows的驅(qū)動(dòng)來(lái)實(shí)現(xiàn)API調(diào)用的,這里我們還真應(yīng)該好好琢磨琢磨。

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • C#如何創(chuàng)建自定義特性

    C#如何創(chuàng)建自定義特性

    這篇文章主要介紹了C#如何創(chuàng)建自定義特性,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下
    2021-04-04
  • C#實(shí)現(xiàn)讀取DataSet數(shù)據(jù)并顯示在ListView控件中的方法

    C#實(shí)現(xiàn)讀取DataSet數(shù)據(jù)并顯示在ListView控件中的方法

    這篇文章主要介紹了C#實(shí)現(xiàn)讀取DataSet數(shù)據(jù)并顯示在ListView控件中的方法,涉及C#操作DataSet及ListView控件的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-10-10
  • 在C#中捕獲內(nèi)存不足異常

    在C#中捕獲內(nèi)存不足異常

    這篇文章主要介紹了在C#中捕獲內(nèi)存不足異常,下面文章內(nèi)容圍繞如何在C#中捕獲內(nèi)存不足異常的相關(guān)資料展開(kāi)詳細(xì)內(nèi)容,具有一定的參考價(jià)值,需要的小伙伴可以參考一下,希望對(duì)你有所幫助
    2021-12-12
  • C#窗體顯示留言時(shí)間的方法

    C#窗體顯示留言時(shí)間的方法

    這篇文章主要介紹了C#窗體顯示留言時(shí)間的方法,涉及C#操作時(shí)間的技巧,需要的朋友可以參考下
    2015-03-03
  • .NET Core開(kāi)發(fā)之配置詳解

    .NET Core開(kāi)發(fā)之配置詳解

    這篇文章給大家分享了.NET Core開(kāi)發(fā)中相關(guān)配置的知識(shí)點(diǎn)內(nèi)容,有需要的朋友們可以參考下。
    2018-08-08
  • C#用websocket實(shí)現(xiàn)簡(jiǎn)易聊天功能(服務(wù)端)

    C#用websocket實(shí)現(xiàn)簡(jiǎn)易聊天功能(服務(wù)端)

    這篇文章主要為大家詳細(xì)介紹了C#用websocket實(shí)現(xiàn)簡(jiǎn)易聊天功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • c# 實(shí)現(xiàn)圓形的進(jìn)度條(ProgressBar)

    c# 實(shí)現(xiàn)圓形的進(jìn)度條(ProgressBar)

    這篇文章主要介紹了c# 如何實(shí)現(xiàn)圓形的進(jìn)度條(ProgressBar),幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下
    2021-03-03
  • C#實(shí)現(xiàn)多線程編程的簡(jiǎn)單案例

    C#實(shí)現(xiàn)多線程編程的簡(jiǎn)單案例

    這篇文章介紹了C#實(shí)現(xiàn)多線程編程的簡(jiǎn)單案例,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-04-04
  • WCF分布式開(kāi)發(fā)之MSMQ消息隊(duì)列

    WCF分布式開(kāi)發(fā)之MSMQ消息隊(duì)列

    這篇文章介紹了WCF分布式開(kāi)發(fā)之MSMQ消息隊(duì)列,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-05-05
  • c++換行符知識(shí)點(diǎn)總結(jié)

    c++換行符知識(shí)點(diǎn)總結(jié)

    在本篇文章里小編給大家整理的是關(guān)于c++換行符知識(shí)點(diǎn)總結(jié),需要的朋友們可以參考學(xué)習(xí)下。
    2020-03-03

最新評(píng)論