c# 小票打印

c# 在进行小票打印时大致有三种方法。

1. 使用水晶报表进行打印。可以参考:https://www.cnblogs.com/aitong/p/10717786.html

2. 在 PrintDocument 对象上进行绘图,然后使用其打印方法直接打印。

using CrystalDecisions.CrystalReports.Engine;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Printing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CrTest
{
    public partial class Form1 : Form
    {
        string title = "标题标题标题标题标题标题标题标题标题标题标题";
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //打印预览            
            PrintPreviewDialog ppd = new PrintPreviewDialog();
            PrintDocument pd = new PrintDocument();
            //设置边距
            Margins margin = new Margins(10, 10, 10, 10);
            pd.DefaultPageSettings.Margins = margin;
            int height = 30;
            if (title.Length > 13)
            {
                height = 60;
            }
            //纸张设置默认
            PaperSize pageSize = new PaperSize("First custom size", (int)(58 * 100 / 25.4), height);//58mm   转绘图宽度
            pd.DefaultPageSettings.PaperSize = pageSize;
            //打印事件设置            
            pd.PrintPage += new PrintPageEventHandler(pd_PrintPage);
            ppd.Document = pd;
            ppd.ShowDialog();
            //try
            //{
            //    pd.Print();
            //}
            //catch (Exception ex)
            //{
            //    MessageBox.Show(ex.Message, "打印出错", MessageBoxButtons.OK, MessageBoxIcon.Error);
            //    pd.PrintController.OnEndPrint(pd, new PrintEventArgs());
            //}
        }

        private void pd_PrintPage(object sender, PrintPageEventArgs e)
        {
            Font font = new Font("Arial", 10, System.Drawing.FontStyle.Regular);
            string text = title;
            int yLocation = e.MarginBounds.Y;
            int center = e.PageSettings.PaperSize.Width / 2 ;
            int heightStep = 0;
            while (text.Length > 0)
            {
                string printStr;
                if (text.Length > 13)
                {
                    printStr = text.Substring(0, 13);
                    text = text.Substring(13);
                }
                else
                {
                    printStr = text;
                    text = "";
                }
                SizeF size = e.Graphics.MeasureString(printStr, font);
                heightStep =Convert.ToInt32( size.Height * 1.3);
                e.Graphics.DrawString(printStr, font, System.Drawing.Brushes.Black, center - size.Width / 2, yLocation);
                yLocation += heightStep;
            }
        }
    }
}

3. 使用 ESC/POS 控制指令

注意 SendStringToPrinter 这个接口。

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
//https://www.cnblogs.com/QiuTianBaBa/p/6730829.html
//https://blog.csdn.net/andrewniu/article/details/80353655
namespace Evet2Basic.Model.Print.Report
{
    public class RawPrint
    {
        // Structure and API declarions:
        [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;
        }
        [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);

        // SendBytesToPrinter()
        // When the function is given a printer name and an unmanaged array
        // of bytes, the function sends those bytes to the print queue.
        // Returns true on success, false on failure.
        private 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; // Assume failure unless you specifically succeed.

            di.pDocName = "XiaoPiao";
            di.pDataType = "RAW";

            // Open the printer.
            if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
            {
                // Start a document.
                if (StartDocPrinter(hPrinter, 1, di))
                {
                    // Start a page.
                    if (StartPagePrinter(hPrinter))
                    {
                        // Write your bytes.
                        bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
                        EndPagePrinter(hPrinter);
                    }
                    EndDocPrinter(hPrinter);
                }
                ClosePrinter(hPrinter);
            }
            // If you did not succeed, GetLastError may give more information
            // about why not.
            if (bSuccess == false)
            {
                dwError = Marshal.GetLastWin32Error();
            }
            return bSuccess;
        }

        private static bool SendFileToPrinter(string szPrinterName, string szFileName)
        {
            // Open the file.
            FileStream fs = new FileStream(szFileName, FileMode.Open);
            // Create a BinaryReader on the file.
            BinaryReader br = new BinaryReader(fs);
            // Dim an array of bytes big enough to hold the file's contents.
            Byte[] bytes = new Byte[fs.Length];
            bool bSuccess = false;
            // Your unmanaged pointer.
            IntPtr pUnmanagedBytes = new IntPtr(0);
            int nLength;

            nLength = Convert.ToInt32(fs.Length);
            // Read the contents of the file into the array.
            bytes = br.ReadBytes(nLength);
            // Allocate some unmanaged memory for those bytes.
            pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength);
            // Copy the managed byte array into the unmanaged array.
            Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength);
            // Send the unmanaged bytes to the printer.
            bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength);
            // Free the unmanaged memory that you allocated earlier.
            Marshal.FreeCoTaskMem(pUnmanagedBytes);
            return bSuccess;
        }

        public static bool SendBytesToPrinter(string szPrinterName, byte[] buf)
        {
            bool bSuccess = false;
            // Your unmanaged pointer.
            IntPtr pUnmanagedBytes = new IntPtr(0);
            // Allocate some unmanaged memory for those bytes.
            pUnmanagedBytes = Marshal.AllocCoTaskMem(buf.Length);
            // Copy the managed byte array into the unmanaged array.
            Marshal.Copy(buf, 0, pUnmanagedBytes, buf.Length);
            // Send the unmanaged bytes to the printer.
            bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, buf.Length);
            // Free the unmanaged memory that you allocated earlier.
            Marshal.FreeCoTaskMem(pUnmanagedBytes);
            return bSuccess;
        }

        /// <summary>
        /// 切纸
        /// </summary>
        /// <param name="szPrinterName">打印机名</param>
        /// <returns></returns>
        public static bool Cut(string szPrinterName)
        {
            bool bSuccess = false;

            IntPtr pUnmanagedBytes = new IntPtr(0);

            byte[] data = new byte[] { 0x1B, 0x69 };
            pUnmanagedBytes = Marshal.AllocCoTaskMem(data.Length);
            Marshal.Copy(data, 0, pUnmanagedBytes, data.Length);
            bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, data.Length);
            Marshal.FreeCoTaskMem(pUnmanagedBytes);
            return true;
        }


        public static bool SendBytesToPrinterImg(string szPrinterName, Bitmap bmp, bool needWarning)
        {
            bool bSuccess = false;

            //Byte[] byte_send = Encoding.GetEncoding("GB2312").GetBytes("x1bx40");
            IntPtr pUnmanagedBytes = new IntPtr(0);
            //pUnmanagedBytes = Marshal.AllocCoTaskMem(byte_send.Length);
            //Marshal.Copy(byte_send, 0, pUnmanagedBytes, byte_send.Length);
            //bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, byte_send.Length);
            //Marshal.FreeCoTaskMem(pUnmanagedBytes);

            byte[] data = new byte[] { 0x1B, 0x33, 0x00 };
            //pUnmanagedBytes = new IntPtr(0);
            pUnmanagedBytes = Marshal.AllocCoTaskMem(data.Length);
            Marshal.Copy(data, 0, pUnmanagedBytes, data.Length);
            bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, data.Length);
            Marshal.FreeCoTaskMem(pUnmanagedBytes);
            data[0] = (byte)'x00';
            data[1] = (byte)'x00';
            data[2] = (byte)'x00';

            Color pixelColor;

            // ESC * m nL nH 点阵图  
            byte[] escBmp = new byte[] { 0x1B, 0x2A, 0x00, 0x00, 0x00 };
            escBmp[2] = (byte)'x21';
            //nL, nH  
            escBmp[3] = (byte)(bmp.Width % 256);
            escBmp[4] = (byte)(bmp.Width / 256);

            // data  
            for (int i = 0; i < (bmp.Height / 24) + 1; i++)
            {
                //pUnmanagedBytes = new IntPtr(0);
                pUnmanagedBytes = Marshal.AllocCoTaskMem(escBmp.Length);
                Marshal.Copy(escBmp, 0, pUnmanagedBytes, escBmp.Length);
                bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, escBmp.Length);
                Marshal.FreeCoTaskMem(pUnmanagedBytes);

                byte[] temptype = new byte[bmp.Width * 3];
                int lengthNow = 0;
                for (int j = 0; j < bmp.Width; j++)
                {
                    for (int k = 0; k < 24; k++)
                    {
                        if (((i * 24) + k) < bmp.Height)   // if within the BMP size  
                        {
                            pixelColor = bmp.GetPixel(j, (i * 24) + k);
                            if (pixelColor.R == 0)
                            {
                                data[k / 8] += (byte)(128 >> (k % 8));
                            }
                        }
                    }
                    data.CopyTo(temptype, lengthNow);
                    lengthNow += 3;

                    data[0] = (byte)'x00';
                    data[1] = (byte)'x00';
                    data[2] = (byte)'x00';
                }

                //pUnmanagedBytes = new IntPtr(0);
                pUnmanagedBytes = Marshal.AllocCoTaskMem(temptype.Length);
                Marshal.Copy(temptype, 0, pUnmanagedBytes, temptype.Length);
                bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, temptype.Length);
                Marshal.FreeCoTaskMem(pUnmanagedBytes);
                System.Threading.Thread.Sleep(10);
            }
            byte[] dataClear = new byte[] { 0x1B, 0x40 };
            pUnmanagedBytes = Marshal.AllocCoTaskMem(dataClear.Length);
            Marshal.Copy(dataClear, 0, pUnmanagedBytes, dataClear.Length);
            bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, dataClear.Length);
            Marshal.FreeCoTaskMem(pUnmanagedBytes);
            return bSuccess;
        }

        public static bool SendStringToPrinter(string szPrinterName, string szString)
        {
            try
            {
                //指令见打印机官方文档    http://www.xprinter.net/index.php/Server/index/cid/3
                byte[] smallArray = new byte[] { 29, 33, 0 };
                List<byte> list = new List<byte>();

                list.AddRange(smallArray);
                while (szString.Contains("<B>") || szString.Contains("<A>"))
                {
                    if (!szString.Contains("<B>"))
                    {
                        ReplaceAB(ref szString, ref list, 2);
                    }
                    else if (!szString.Contains("<A>"))
                    {
                        ReplaceAB(ref szString, ref list, 3);
                    }
                    else
                    {
                        int indexA = szString.IndexOf("<A>");
                        int indexB = szString.IndexOf("<B>");
                        if (indexA < indexB)
                        {
                            ReplaceAB(ref szString, ref list, 2);
                        }
                        else
                        {
                            ReplaceAB(ref szString, ref list, 3);
                        }
                    }
                }
                Encoding enc = Encoding.GetEncoding("gb2312");
                list.AddRange(enc.GetBytes(szString));
                return RawPrint.SendBytesToPrinter(szPrinterName, list.ToArray());
            }
            catch (Exception)
            {
                return false;
            }
        }

        private static void ReplaceAB(ref string szString, ref List<byte> list, int mul)
        {
            //指令见打印机官方文档    http://www.xprinter.net/index.php/Server/index/cid/3
            string replaceStr1 = "<B>";
            string replaceStr2 = "</B>";
            byte[] smallArray = new byte[] { 29, 33, 0 };
            byte[] bigArray = new byte[] { 29, 33, 34 };   //放大三倍    //29, 33字体放大指令  34放大倍数 ( 0一倍    17两倍   34三倍     51四倍    68五倍     85六倍)
            if (mul == 2)
            {
                replaceStr1 = "<A>";
                replaceStr2 = "</A>";
                bigArray = new byte[] { 29, 33, 17 };   //放大两倍
            }
            Encoding enc = Encoding.GetEncoding("gb2312");
            int index = szString.IndexOf(replaceStr1);
            string first = szString.Substring(0, index);
            list.AddRange(enc.GetBytes(first));//第一段
            list.AddRange(bigArray);//变成大写
            szString = szString.Substring(index + 3);
            int index2 = szString.IndexOf(replaceStr2);
            string second = szString.Substring(0, index2);
            list.AddRange(enc.GetBytes(second));//大写段
            list.AddRange(smallArray);//变小写
            szString = szString.Substring(index2 + 4);
        }
    }
}
原文地址:https://www.cnblogs.com/aitong/p/10730264.html