最近需要做一個列印的功能,於是在網上找到了這麼一個方法。 以上就是全部代碼了,調用就很簡單了,方法如下: ...
最近需要做一個列印的功能,於是在網上找到了這麼一個方法。
[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; } public class PrintCode { [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> /// 該方法把非托管記憶體中的位元組數組發送到印表機的列印隊列 /// </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 == false) { 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(); } }
以上就是全部代碼了,調用就很簡單了,方法如下:
private void Print_Click(object sender, EventArgs e) { //列印文件的路徑,該方法獲取到的文件路徑在應用程式 bin\Debug\ 目錄下,所以 ../../ 向上兩級目錄 string fileName = AppDomain.CurrentDomain.BaseDirectory + @"../../File/demo.txt"; if (PrintCode.SendFileToPrinter("PrinterName", fileName)) { MessageBox.Show("文件已成功發送至列印隊列!","提示信息"); } }