using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Net.Sockets; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Windows.Forms; using NLog; namespace POSV.Printer { public class PrinterUtils { private static Logger logger = NLog.LogManager.GetCurrentClassLogger(); public static object _lock = new object(); private static void OpenSerialPort(PrinterObject pobj , List content) { try { IntPtr _IntPtr = IntPtr.Zero; string _portName = pobj.Data[PrinterObject.COM_PORT_NAME]; string _portBaud = pobj.Data[PrinterObject.COM_PORT_BAUD]; var regex = new Regex("COM" , RegexOptions.IgnoreCase); int iport = 0; int.TryParse(regex.Replace(_portName , "") , out iport); uint baud = 0; uint.TryParse(_portBaud , out baud); _IntPtr = ByPosDll.POS_Open(_portName , baud , 8 , ByPosDll.POS_COM_ONESTOPBIT , ByPosDll.POS_COM_NOPARITY , ByPosDll.POS_COM_NO_HANDSHAKE); if ((int)_IntPtr == -1) { logger.Error("串口打开失败!"); } if ((int)_IntPtr != -1 && content != null && content.Count > 0) { if (ByPosDll.POS_StartDoc()) { foreach (var p in content) { switch (p.Format) { case RowFormat.Barcode: { if (p.Content != null && !string.IsNullOrEmpty(p.Content.ToString())) { byte[] by_SendData = System.Text.Encoding.Default.GetBytes(p.Content.ToString()); ByPosDll.POS_WriteFile(_IntPtr , by_SendData , (uint)by_SendData.Length); } byte[] data = BuilderBitmapByFile(p.BitmapFile); ByPosDll.POS_WriteFile(_IntPtr , data , (uint)data.Length); ByPosDll.POS_WriteFile(_IntPtr , new byte[] { 0x0a } , 1); } break; case RowFormat.QRCode: { if (p.Content != null && !string.IsNullOrEmpty(p.Content.ToString())) { byte[] by_SendData = System.Text.Encoding.Default.GetBytes(p.Content.ToString()); ByPosDll.POS_WriteFile(_IntPtr , by_SendData , (uint)by_SendData.Length); } byte[] data = BuilderBitmapByFile(p.BitmapFile); ByPosDll.POS_WriteFile(_IntPtr , data , (uint)data.Length); ByPosDll.POS_WriteFile(_IntPtr , new byte[] { 0x0a } , 1); } break; case RowFormat.Bitmap: { if (p.Content != null && !string.IsNullOrEmpty(p.Content.ToString())) { byte[] by_SendData = System.Text.Encoding.Default.GetBytes(p.Content.ToString()); ByPosDll.POS_WriteFile(_IntPtr , by_SendData , (uint)by_SendData.Length); } byte[] data = BuilderBitmapByFile(p.BitmapFile); ByPosDll.POS_WriteFile(_IntPtr , data , (uint)data.Length); ByPosDll.POS_WriteFile(_IntPtr , new byte[] { 0x0a } , 1); } break; default: { byte[] by_SendData = System.Text.Encoding.Default.GetBytes(p.Content.ToString()); ByPosDll.POS_WriteFile(_IntPtr , by_SendData , (uint)by_SendData.Length); ByPosDll.POS_WriteFile(_IntPtr , new byte[] { 0x0a } , 1); } break; } } ByPosDll.POS_EndDoc(); } } else { logger.Error("不满足打印条件!"); } } catch (Exception ex) { logger.Error(ex , "串口打印异常"); } finally { ByPosDll.POS_Close(); } } private static void OpenNetPort(PrinterObject pobj , List content) { IntPtr _IntPtr = IntPtr.Zero; string _ipAddress = pobj.Data[PrinterObject.NET_IP_ADDRESS]; ; _IntPtr = ByPosDll.POS_Open(_ipAddress , 0 , 0 , 0 , 0 , ByPosDll.POS_OPEN_NETPORT); if ((int)_IntPtr == -1) { logger.Error("网口打开失败!重试一次!"); Thread.Sleep(1000); _IntPtr = ByPosDll.POS_Open(_ipAddress, 0, 0, 0, 0, ByPosDll.POS_OPEN_NETPORT); if ((int)_IntPtr == -1) { logger.Error("重试网口依然打开失败!放弃打印!"); } } if ((int)_IntPtr != -1 && content != null && content.Count > 0) { if (ByPosDll.POS_StartDoc()) { foreach (var p in content) { switch (p.Format) { case RowFormat.Barcode: { if (p.Content != null && !string.IsNullOrEmpty(p.Content.ToString())) { byte[] by_SendData = System.Text.Encoding.Default.GetBytes(p.Content.ToString()); ByPosDll.POS_WriteFile(_IntPtr , by_SendData , (uint)by_SendData.Length); } byte[] data = BuilderBitmapByFile(p.BitmapFile); ByPosDll.POS_WriteFile(_IntPtr , data , (uint)data.Length); ByPosDll.POS_WriteFile(_IntPtr , new byte[] { 0x0a } , 1); } break; case RowFormat.QRCode: { if (p.Content != null && !string.IsNullOrEmpty(p.Content.ToString())) { byte[] by_SendData = System.Text.Encoding.Default.GetBytes(p.Content.ToString()); ByPosDll.POS_WriteFile(_IntPtr , by_SendData , (uint)by_SendData.Length); } byte[] data = BuilderBitmapByFile(p.BitmapFile); ByPosDll.POS_WriteFile(_IntPtr , data , (uint)data.Length); ByPosDll.POS_WriteFile(_IntPtr , new byte[] { 0x0a } , 1); } break; case RowFormat.Bitmap: { if (p.Content != null && !string.IsNullOrEmpty(p.Content.ToString())) { byte[] by_SendData = System.Text.Encoding.Default.GetBytes(p.Content.ToString()); ByPosDll.POS_WriteFile(_IntPtr , by_SendData , (uint)by_SendData.Length); } byte[] data = BuilderBitmapByFile(p.BitmapFile); ByPosDll.POS_WriteFile(_IntPtr , data , (uint)data.Length); ByPosDll.POS_WriteFile(_IntPtr , new byte[] { 0x0a } , 1); } break; default: { byte[] by_SendData = System.Text.Encoding.Default.GetBytes(p.Content.ToString()); ByPosDll.POS_WriteFile(_IntPtr , by_SendData , (uint)by_SendData.Length); ByPosDll.POS_WriteFile(_IntPtr , new byte[] { 0x0a } , 1); } break; } } ByPosDll.POS_EndDoc(); } } } private static void OpenParallelPort(PrinterObject pobj , List content) { IntPtr _IntPtr = IntPtr.Zero; string _lptName = pobj.Data[PrinterObject.LPT_NAME]; _IntPtr = ByPosDll.POS_Open(_lptName , 0 , 0 , 0 , 0 , ByPosDll.POS_OPEN_PARALLEL_PORT); if ((int)_IntPtr == -1) { logger.Error("并口打开失败!"); } if ((int)_IntPtr != -1 && content != null && content.Count > 0) { if (ByPosDll.POS_StartDoc()) { foreach (var p in content) { switch (p.Format) { case RowFormat.Barcode: { if (p.Content != null && !string.IsNullOrEmpty(p.Content.ToString())) { byte[] by_SendData = System.Text.Encoding.Default.GetBytes(p.Content.ToString()); ByPosDll.POS_WriteFile(_IntPtr , by_SendData , (uint)by_SendData.Length); } byte[] data = BuilderBitmapByFile(p.BitmapFile); ByPosDll.POS_WriteFile(_IntPtr , data , (uint)data.Length); ByPosDll.POS_WriteFile(_IntPtr , new byte[] { 0x0a } , 1); } break; case RowFormat.QRCode: { if (p.Content != null && !string.IsNullOrEmpty(p.Content.ToString())) { byte[] by_SendData = System.Text.Encoding.Default.GetBytes(p.Content.ToString()); ByPosDll.POS_WriteFile(_IntPtr , by_SendData , (uint)by_SendData.Length); } byte[] data = BuilderBitmapByFile(p.BitmapFile); ByPosDll.POS_WriteFile(_IntPtr , data , (uint)data.Length); ByPosDll.POS_WriteFile(_IntPtr , new byte[] { 0x0a } , 1); } break; case RowFormat.Bitmap: { if (p.Content != null && !string.IsNullOrEmpty(p.Content.ToString())) { byte[] by_SendData = System.Text.Encoding.Default.GetBytes(p.Content.ToString()); ByPosDll.POS_WriteFile(_IntPtr , by_SendData , (uint)by_SendData.Length); } byte[] data = BuilderBitmapByFile(p.BitmapFile); ByPosDll.POS_WriteFile(_IntPtr , data , (uint)data.Length); ByPosDll.POS_WriteFile(_IntPtr , new byte[] { 0x0a } , 1); } break; default: { byte[] by_SendData = System.Text.Encoding.Default.GetBytes(p.Content.ToString()); ByPosDll.POS_WriteFile(_IntPtr , by_SendData , (uint)by_SendData.Length); ByPosDll.POS_WriteFile(_IntPtr , new byte[] { 0x0a } , 1); } break; } } ByPosDll.POS_EndDoc(); } } } public static void OpenDrivePort(PrinterObject pobj , List content) { IntPtr _IntPtr = IntPtr.Zero; string _driveName = pobj.Data[PrinterObject.DRIVE_NAME]; _IntPtr = ByPosDll.POS_Open(_driveName , 0 , 0 , 0 , 0 , ByPosDll.POS_OPEN_PRINTNAME); if ((int)_IntPtr == -1) { logger.Error("驱动打开失败!"); } if ((int)_IntPtr != -1 && content != null && content.Count > 0) { if (ByPosDll.POS_StartDoc()) { foreach (var p in content) { switch (p.Format) { case RowFormat.Barcode: { if (p.Content != null && !string.IsNullOrEmpty(p.Content.ToString())) { byte[] by_SendData = System.Text.Encoding.Default.GetBytes(p.Content.ToString()); ByPosDll.POS_WriteFile(_IntPtr , by_SendData , (uint)by_SendData.Length); } byte[] data = BuilderBitmapByFile(p.BitmapFile); ByPosDll.POS_WriteFile(_IntPtr , data , (uint)data.Length); ByPosDll.POS_WriteFile(_IntPtr , new byte[] { 0x0a } , 1); } break; case RowFormat.QRCode: { if (p.Content != null && !string.IsNullOrEmpty(p.Content.ToString())) { byte[] by_SendData = System.Text.Encoding.Default.GetBytes(p.Content.ToString()); ByPosDll.POS_WriteFile(_IntPtr , by_SendData , (uint)by_SendData.Length); } byte[] data = BuilderBitmapByFile(p.BitmapFile); ByPosDll.POS_WriteFile(_IntPtr , data , (uint)data.Length); ByPosDll.POS_WriteFile(_IntPtr , new byte[] { 0x0a } , 1); } break; case RowFormat.Bitmap: { if (p.Content != null && !string.IsNullOrEmpty(p.Content.ToString())) { byte[] by_SendData = System.Text.Encoding.Default.GetBytes(p.Content.ToString()); ByPosDll.POS_WriteFile(_IntPtr , by_SendData , (uint)by_SendData.Length); } byte[] data = BuilderBitmapByFile(p.BitmapFile); ByPosDll.POS_WriteFile(_IntPtr , data , (uint)data.Length); ByPosDll.POS_WriteFile(_IntPtr , new byte[] { 0x0a } , 1); } break; default: { byte[] by_SendData = System.Text.Encoding.Default.GetBytes(p.Content.ToString()); ByPosDll.POS_WriteFile(_IntPtr , by_SendData , (uint)by_SendData.Length); ByPosDll.POS_WriteFile(_IntPtr , new byte[] { 0x0a } , 1); } break; } } ByPosDll.POS_EndDoc(); } } } public static void OpenBeiyangUsbPort(PrinterObject pobj , List content) { IntPtr _IntPtr = IntPtr.Zero; _IntPtr = ByPosDll.POS_Open("BYUSB-0" , 0 , 0 , 0 , 0 , ByPosDll.POS_OPEN_BYUSB_PORT); if (content != null && content.Count > 0) { if (ByPosDll.POS_StartDoc()) { foreach (var p in content) { switch (p.Format) { case RowFormat.Barcode: { if (p.Content != null && !string.IsNullOrEmpty(p.Content.ToString())) { byte[] by_SendData = System.Text.Encoding.Default.GetBytes(p.Content.ToString()); ByPosDll.POS_WriteFile(_IntPtr , by_SendData , (uint)by_SendData.Length); } byte[] data = BuilderBitmapByFile(p.BitmapFile); ByPosDll.POS_WriteFile(_IntPtr , data , (uint)data.Length); ByPosDll.POS_WriteFile(_IntPtr , new byte[] { 0x0a } , 1); } break; case RowFormat.QRCode: { if (p.Content != null && !string.IsNullOrEmpty(p.Content.ToString())) { byte[] by_SendData = System.Text.Encoding.Default.GetBytes(p.Content.ToString()); ByPosDll.POS_WriteFile(_IntPtr , by_SendData , (uint)by_SendData.Length); } byte[] data = BuilderBitmapByFile(p.BitmapFile); ByPosDll.POS_WriteFile(_IntPtr , data , (uint)data.Length); ByPosDll.POS_WriteFile(_IntPtr , new byte[] { 0x0a } , 1); } break; case RowFormat.Bitmap: { if (p.Content != null && !string.IsNullOrEmpty(p.Content.ToString())) { byte[] by_SendData = System.Text.Encoding.Default.GetBytes(p.Content.ToString()); ByPosDll.POS_WriteFile(_IntPtr , by_SendData , (uint)by_SendData.Length); } byte[] data = BuilderBitmapByFile(p.BitmapFile); ByPosDll.POS_WriteFile(_IntPtr , data , (uint)data.Length); ByPosDll.POS_WriteFile(_IntPtr , new byte[] { 0x0a } , 1); } break; default: { byte[] by_SendData = System.Text.Encoding.Default.GetBytes(p.Content.ToString()); ByPosDll.POS_WriteFile(_IntPtr , by_SendData , (uint)by_SendData.Length); ByPosDll.POS_WriteFile(_IntPtr , new byte[] { 0x0a } , 1); } break; } } ByPosDll.POS_EndDoc(); } } } private static void OpenYankeUsbPort(PrinterObject pobj , List content) { YkPosDll.YkOpenDevice(13 , 0); foreach (var p in content) { switch (p.Format) { case RowFormat.Barcode: { if (p.Content != null && !string.IsNullOrEmpty(p.Content.ToString())) { YkPosDll.YkPrintStr(p.Content); } YkPosDll.YkDownloadBitmapAndPrint(p.BitmapFile , 0); } break; case RowFormat.QRCode: { if (p.Content != null && !string.IsNullOrEmpty(p.Content.ToString())) { YkPosDll.YkPrintStr(p.Content); } YkPosDll.YkDownloadBitmapAndPrint(p.BitmapFile , 0); } break; case RowFormat.Bitmap: { if (p.Content != null && !string.IsNullOrEmpty(p.Content.ToString())) { YkPosDll.YkPrintStr(p.Content); } YkPosDll.YkDownloadBitmapAndPrint(p.BitmapFile , 0); } break; default: { YkPosDll.YkPrintStr(p.Content); YkPosDll.YkFeedPaper(); } break; } } } public static Tuple PrintContent(PrinterObject pobj , List content) { //Yao 2023-06-26 微信点餐 更改为微信堂食和微信外带 StringBuilder sb = new StringBuilder(); string str = ""; string replacedStr = ""; int index = 0; foreach (var p in content) { sb = p.Content; str = sb.ToString(); index = str.IndexOf("No.T"); if (index != -1) { // 使用字符串的 Replace 方法进行替换 index = str.IndexOf("微信点餐"); if (index != -1) { replacedStr = str.Replace("微信点餐", "微信堂食"); // 将替换后的字符串转换回 StringBuilder sb = new StringBuilder(replacedStr); p.Content = sb; } } index = str.IndexOf("No.D"); if (index != -1) { // 使用字符串的 Replace 方法进行替换 index = str.IndexOf("微信点餐"); if (index != -1) { replacedStr = str.Replace("微信点餐", "微信外带"); // 将替换后的字符串转换回 StringBuilder sb = new StringBuilder(replacedStr); p.Content = sb; } } } logger.Info("打印入口,打印内容:" + JSON.Serialize(content)); lock (_lock) { Tuple result = null; try { IntPtr _IntPtr = IntPtr.Zero; var dynamic = pobj.DynamicLibrary; var portType = pobj.PortType; switch (portType) { case PortType.串口: { OpenSerialPort(pobj , content); } break; case PortType.网口: { OpenNetPort(pobj , content); } break; case PortType.并口: { OpenParallelPort(pobj , content); } break; case PortType.驱动: { OpenDrivePort(pobj , content); } break; case PortType.USB: { switch (dynamic) { case DynamicLibrary.北洋打印机专用: { OpenBeiyangUsbPort(pobj , content); } break; case DynamicLibrary.通用打印模式: default: { OpenYankeUsbPort(pobj , content); } break; } } break; case PortType.None: { } break; } result = new Tuple(true , "打印成功"); } catch (Exception ex) { result = new Tuple(false , "打印出现错误,请检查配置"); } finally { ByPosDll.POS_Close(); Thread.Sleep(10); YkPosDll.YkCloseDevice(); Thread.Sleep(10); //清除临时缓存的文件 foreach (var p in content) { switch (p.Format) { case RowFormat.Barcode: case RowFormat.QRCode: case RowFormat.Bitmap: { if (p.BitmapFile != null && File.Exists(p.BitmapFile)) { FileHelper.KillFile(p.BitmapFile , 2); } } break; } Thread.Sleep(10); } } return result; } } private static byte[] BuilderBitmapByFile(string filename) { using (MemoryStream stream = new MemoryStream()) { using (BinaryWriter bw = new BinaryWriter(stream)) { //设置字符行间距为n点行 byte[] data = new byte[] { 0x1B , 0x33 , 0x00 }; bw.Write(data); data[0] = (byte)'\x00'; data[1] = (byte)'\x00'; data[2] = (byte)'\x00'; Color pixelColor; //获取图片 Bitmap bmp = new Bitmap(filename , true); //ESC * m nL nH d1…dk 选择位图模式 // 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); //循环图片像素打印图片 //循环高 for (int i = 0; i < (bmp.Height / 24) + 1; i++) { //设置模式为位图模式 bw.Write(escBmp); 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,24个像素 bw.Write(data); data[0] = (byte)'\x00'; data[1] = (byte)'\x00'; data[2] = (byte)'\x00'; // Clear to Zero. } //换行,打印第二行 byte[] data2 = { 0x0A }; bw.Write(data2); } bw.Flush(); bmp.Dispose(); return stream.ToArray(); } } } public static Tuple CheckPrinterStatus(PrinterObject pobj) { Tuple result = null; TelnetConnection telnet = null; IntPtr hPrinter = IntPtr.Zero; try { switch (pobj.PortType) { case PortType.串口: { string _portName = pobj.Data[PrinterObject.COM_PORT_NAME]; string _portBaud = pobj.Data[PrinterObject.COM_PORT_BAUD]; var regex = new Regex("COM" , RegexOptions.IgnoreCase); int iport = 0; int.TryParse(regex.Replace(_portName , "") , out iport); uint baud = 0; uint.TryParse(_portBaud , out baud); IntPtr _IntPtr = ByPosDll.POS_Open(_portName , baud , 8 , ByPosDll.POS_COM_ONESTOPBIT , ByPosDll.POS_COM_NOPARITY , ByPosDll.POS_COM_NO_HANDSHAKE); if ((int)_IntPtr != -1) { result = new Tuple(true , "打印机串口检测正常"); } else { result = new Tuple(false , "打印机串口打开失败,请检测配置"); } } break; case PortType.并口: { string _lptName = pobj.Data[PrinterObject.LPT_NAME]; IntPtr _IntPtr = ByPosDll.POS_Open(_lptName , 0 , 0 , 0 , 0 , ByPosDll.POS_OPEN_PARALLEL_PORT); if ((int)_IntPtr != -1) { result = new Tuple(true , "打印机并口检测正常"); } else { result = new Tuple(false , "打印机并口检测错误"); } } break; case PortType.网口: { telnet = new TelnetConnection(pobj.Data[PrinterObject.NET_IP_ADDRESS] , 9100 , 1000); if (telnet.IsConnected) { result = new Tuple(true , "网路打印机连接正常"); } else { result = new Tuple(false , "网路打印机连接超时,请检测网络配置"); } } break; case PortType.USB: { switch (pobj.DynamicLibrary) { case DynamicLibrary.北洋打印机专用: { IntPtr _IntPtr = ByPosDll.POS_Open("BYUSB-0" , 0 , 0 , 0 , 0 , ByPosDll.POS_OPEN_BYUSB_PORT); if ((int)_IntPtr != -1) { result = new Tuple(true , "北洋打印机USB口检测正常"); } else { result = new Tuple(false , "北洋打印机USB口检测错误"); } } break; default: if (YkPosDll.YkOpenDevice(13 , 0) == 0) { result = new Tuple(true , "打印机USB口工作正常"); } else { result = new Tuple(false , "打印机USB口不能正常工作,请检测配置"); } break; } } break; case PortType.驱动: { string _driveName = pobj.Data[PrinterObject.DRIVE_NAME]; IntPtr _IntPtr = ByPosDll.POS_Open(_driveName , 0 , 0 , 0 , 0 , ByPosDll.POS_OPEN_PRINTNAME); if ((int)_IntPtr != -1) { result = new Tuple(true , "打印机驱动检测正常"); } else { result = new Tuple(false , "打印机驱动检测错误"); } } break; default: break; } } catch (SocketException sex) { result = new Tuple(false , "连接网络打印机异常,请检查配置"); } catch (TimeoutException tex) { result = new Tuple(false , "连接网络打印机超时,请检查配置"); } catch (Exception ex) { result = new Tuple(false , "打印测试出现异常,请检查配置"); } finally { if (telnet != null) { telnet.DisConnect(); } YkPosDll.YkCloseDevice(); ByPosDll.POS_Close(); } return result; } } }