ZPLII 语言编程基础
链接:https://pan.baidu.com/s/1QTLnnBPgdje7bZ9xMublgQ
提取码:tfu9
0.打印条形码1
搬运出处: https://www.geek-share.com/detail/2623522761.html
code-----------------------------
^XA
^PW1000
^MD30
^LH0,0
#CN_DATA1#;|宋体|20|15|^FO150,0
#CN_DATA2#;|宋体|20|15|^FO650,0
^FO70,0^BY2.0,3.0^BCN,120,Y,N,N,A^FD#ID1#^FS
^FO570,0^BY2.0,3.0^BCN,120,Y,N,N,A^FD#ID2#^FS
^PQ1,0,1,Y
^XZ
code-----------------------------
说明------------------------------
^XA和^XZ:分别代表一个指令块的开始和结束, 是固定的东西。 ^PW:打印宽度,如果宽度较小,则会出现打印不全的效果。 ^MD:设置标签颜色的深度,取值范围为 -30 to 30,上面的指令将颜色调到了最深。 ^LH:设置条码纸的边距,本模板未进行设置。 以下以字符串abc^edf~L000001^L000002为例进行说明(abc、edf分别为汉字,L000001、L000002为条形码值) #CN_DATA1#:为abc的占位符。 #CN_DATA2#:为edf的占位符。 |宋体|20|15|:指字体为宋体,字符高度为20,宽度为15 ^FO:设置条码左上角的位置的坐标(70,0)。 ^BY:设置条形码显示样式, 这是该模板最重要的一个部分, 2.0是条码的缩放级别(可接受的数值:1-10点 ),这个数值下打出的条码很小, 3.0是条码中粗细柱的比例(可接受的数值:2.0到3.0,增量0.1,对固定比例的条码无效 ), 120是条码高度。 ^BCN:是打印code128的指令。 ^FD:设置要打印的内容 ^FS:表示换行 #ID1#:指L000001 #ID2#:指L000002 ^PQ50,10,1,Y:打印总数50张标签每个序列号只打一张。打印每组数量是10,但在每组间不暂停。 ^PQ50,10,1,N:打印总数50张标签每个序列号只打一张。打印每数量是10,每组打印后暂停。 这里可以写成^PQ1,0,1,Y,即每次打印一张,不暂停。因为打印总张数可以在程序中进行控制。
说明------------------------------
效果:
1. ZPL 二维码打印
二维码打印 ^XA ^FO20,20 ^BQ,2,10 ^FDLA,0123456789ABCD 2D code^FS ^XZ 10.二维码:^BQ ^BQ字段位置,模型,放大倍数(^BQ,2,10 无旋转,模型:增强,放大倍数:10) ^BQ =二维码条码 a =字段位置 默认值:正常。 其他值: 没有旋转是可用的。^的FW命令不影响旋转。 b =模型 默认值:2(增强) 推荐 其他值:1(原创) c =放大倍数 默认值:1在150 dpi打印机 2在200 dpi打印机 3在300 dpi打印机 其他值:4至10 (c值不同条码大小不同) 11.纠错能力: L级:约可纠错7%的数据码字 M级:约可纠错15%的数据码字 Q级:约可纠错25%的数据码字 H级:约可纠错30%的数据码字
效果:
2.ZPL 设计预览
http://labelary.com/viewer.html
效果:
3.打印条形码2
// 搬运: https://www.geek-share.com/detail/2755709722.html // 准备: // 1. 斑马打印机 型号GT820。 // 2. 斑马打印机驱动。 // 3. 库文件SMT.ZEBRA.dll 和 SMT.ZEBRA.dll的依赖库文件Fnthex32.dll。 步骤: // 1。调试打印机,安装支持打印机的ZPL驱动(因为所打印标签的模板使用ZPL指令编写的,所以必须选择ZPL)。 // 打印机属性->测试页,打印成功说明调试成功。 // 2。注册 SMT.ZEBRA.dll 文件, cmd 右键->管理员权限运行-> regram 路径/SMT.ZEBRA.dll 。 // Fnthex32.dll库文件貌似不用注册,详见demo中readme.txt。 // 3。给予DLL文件运行权限。右键DLL文件->属性->安全->编辑->添加->everyone->确定->完全控制->确定。 // 4。项目引用 SMT.ZEBRA.dll ,Fnthex32.dll库文件也不用引用。 Imports System.Drawing.Printing.PrinterSettings Imports System.Drawing.Printing Imports System.Text.RegularExpressions Public Class TestZebraPrinterForm Private Sub TestZebraPrinterForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim stringCollection As PrinterSettings.StringCollection = PrinterSettings.InstalledPrinters '’得到已安装的打印机名字。 Dim strPrinterName As String = String.Empty Dim regex As Regex = New Regex("^.*ZPL.*$") '’new 一个正则表达式模板 ,^.*ZPL.*$ 代表包含ZPL的任意字符串。 Dim itemValue As String = "" For Each strName As String In stringCollection strPrinterName = strName.ToString() Printer_ComboBox.Items.Add(strPrinterName) '’添加到组合框。 If regex.IsMatch(strPrinterName) Then '’判断是否满足模板。 itemValue = strPrinterName End If Next Printer_ComboBox.SelectedText = itemValue End Sub Private Sub print_Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles print_Button.Click ''实例化一个打印类 Dim zebraPrinter As Smt.Zebra.ZebraPrinter = New Smt.Zebra.ZebraPrinter() For i = 0 To 2 Dim str1 As String = "名称1:" + "内容" Dim str2 As String = "名称2:" + "内容" Dim str3 As String = "名称3:" + "内容" Dim str4 As String = "名称4:" + "内容" Dim str5 As String = "名称5:" + "内容" Dim str6 As String = "名称6:" + "内容" ''定义一个标签值 Dim barcode As String = "A" + "00000000" + i.ToString ''按照格式,格式化成新的字符串 '’str1 = String.Concat(" ", "^", " ", "~", str1) ''双排条形码 Dim Str As String = String.Concat(str1, "^", str2, "^", str3, "^", str4, "^", str5, "^", str6, "~", barcode) '单排条形码 ''barcodeConfig.TXT:模板配置文件 或barcodeConfig.PRN //一定要大写 ''Printer_ComboBox.Text:打印机名称 Dim Path As String = "barcodeConfig.TXT" zebraPrinter.PrintLabEx(Path, Str, Printer_ComboBox.Text) Next End Sub End Class
下面是打印模板文件barcodeConfig.TXT。
^XA //开始 ^PW1000 //条码最大宽 ^MD30 //颜色深度 ^LH0,0 #CN_DATA1#;|宋体|20|18|^FO100,60 //占位符 //FO横纵坐标 #CN_DATA2#;|宋体|20|18|^FO520,60 //占位符 #CN_DATA3#;|宋体|20|18|^FO100,130 //占位符 #CN_DATA4#;|宋体|20|18|^FO520,130 //占位符 #CN_DATA5#;|宋体|20|18|^FO100,200 //占位符 #CN_DATA6#;|宋体|20|18|^FO520,200 //占位符 //打印条码 //BY缩放大小,条码高度 //(^BCN,120,Y,N,N)打印不旋转的高度为100点的Code128条码。 ^FO280,320^BY4.0,3.0^BCN,120,Y,N,N,A^FD#ID1#^FS ^PQ1,0,1,Y ^XZ //结束
效果:
4.C#编程发送ZPL指令驱动斑马打印机打印标签
搬运地址: http://www.shangxi.xyz/autoinsurancedetail.aspx?id=29 代码下载地址: http://www.shangxi.xyz/upload/2018-04-06/30dc9ef2-59da-4b5c-8797-9f775e5b4d19.zip
5.C#调用斑马打印机打印条码标签(支持COM、LPT、USB、TCP连接方式和ZPL、EPL、CPCL指令)
搬运地址: https://blog.csdn.net/ldljlq/article/details/7338772 在批量打印商品标签时一般都要加上条码或图片,而这类应用大多是使用斑马打印机,所以我也遇到了怎么打印的问题。 一种办法是用标签设计软件做好模板,在标签设计软件中打印,这种办法不用写代码,但对我来说觉得不能接受,所以尝试代码解决问题。 网上搜索一番,找不到什么资料,基本都是说发送ZPL、EPL指令到打印机,而且还是COM/LPT口连接打印机。后来研究.net的打印类库,发现是用绘图方式打印至打印机的,也叫GDI打印,于是思路有了点突破,那我可以用报表工具画好标签,运行报表时,把结果输出位图,再发送至打印机。 后来又找到一种更好的办法,利用标签设计软件做好模板,打印至本地文件,把其中的ZPL、EPL指令拷贝出来,替换其中动态变化的内容为变量名,做成一个模板文本,在代码中动态替换变量,再把指令输出至打印机。 折腾了几天,终于把这两种思路都实现了,顺便解决了USB接口打印机的ZPL、EPL指令发送问题。 今天有点困,改天再详细讲解一下这两种思路的具体实现。 ============================================================================================================== 如何获取标签设计软件输出至打印的ZPL指令?安装好打印机驱动,修改打印机端口,新建一个打印机端口,类型为本地端口,端口名称设置为C:printer.log,再用标签设计软件打印一次,此文件中就有ZPL指令了。 ============================================================================================================== 2012-06-02:发布代码ZebraPrintHelper.cs。 ============================================================================================================== 2013-01-17:发布代码ZebraPrintHelper.cs,修正BUG,新增TCP打印支持Zebra无线打印QL320+系列打印机。已经生产环境实际应用,支持POS小票、吊牌、洗水唛、条码、文本混合标签打印。因涉及公司源码,只能截图VS解决方案给大家看。 ============================================================================================================== ZebraPrintHelper类代码: using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.IO.Ports; using System.Net.Sockets; using System.Runtime.InteropServices; using System.Text; namespace Umisky.BarcodePrint.Core { /// <summary> /// 斑马打印助手,支持LPT/COM/USB/TCP四种模式,适用于标签、票据、条码打印。 /// </summary> public static class ZebraPrintHelper { #region 定义私有字段 /// <summary> /// 线程锁,防止多线程调用。 /// </summary> private static object SyncRoot = new object(); /// <summary> /// ZPL压缩字典 /// </summary> private static List<KeyValue> compressDictionary = new List<KeyValue>(); #endregion #region 定义属性 public static float TcpLabelMaxHeightCM { get; set; } public static int TcpPrinterDPI { get; set; } public static string TcpIpAddress { get; set; } public static int TcpPort { get; set; } public static int Copies { get; set; } public static int Port { get; set; } public static string PrinterName { get; set; } public static bool IsWriteLog { get; set; } public static DeviceType PrinterType { get; set; } public static ProgrammingLanguage PrinterProgrammingLanguage { get; set; } /// <summary> /// 日志保存目录,WEB应用注意不能放在BIN目录下。 /// </summary> public static string LogsDirectory { get; set; } public static byte[] GraphBuffer { get; set; } private static int GraphWidth { get; set; } private static int GraphHeight { get; set; } private static int RowSize { get { return (((GraphWidth) + 31) >> 5) << 2; } } private static int RowRealBytesCount { get { if ((GraphWidth % 8) > 0) { return GraphWidth / 8 + 1; } else { return GraphWidth / 8; } } } #endregion #region 静态构造方法 static ZebraPrintHelper() { initCompressCode(); Port = 1; GraphBuffer = new byte[0]; IsWriteLog = false; LogsDirectory = "logs"; PrinterProgrammingLanguage = ProgrammingLanguage.ZPL; } private static void initCompressCode() { //G H I J K L M N O P Q R S T U V W X Y 对应1,2,3,4……18,19。 //g h i j k l m n o p q r s t u v w x y z 对应20,40,60,80……340,360,380,400。 for (int i = 0; i < 19; i++) { compressDictionary.Add(new KeyValue() { Key = Convert.ToChar(71 + i), Value = i + 1 }); } for (int i = 0; i < 20; i++) { compressDictionary.Add(new KeyValue() { Key = Convert.ToChar(103 + i), Value = (i + 1) * 20 }); } } #endregion #region 日志记录方法 private static void WriteLog(string text, LogType logType) { string endTag = string.Format(" {0} ", new string('=', 80)); string path = string.Format("{0}\{1}-{2}.log", LogsDirectory, DateTime.Now.ToString("yyyy-MM-dd"), logType); if (!Directory.Exists(LogsDirectory)) { Directory.CreateDirectory(LogsDirectory); } if (logType == LogType.Error) { File.AppendAllText(path, string.Format("{0}{1}", text, endTag), Encoding.UTF8); } if (logType == LogType.Print) { File.AppendAllText(path, string.Format("{0}{1}", text, endTag), Encoding.UTF8); } } private static void WriteLog(byte[] bytes, LogType logType) { string endTag = string.Format(" {0} ", new string('=', 80)); string path = string.Format("{0}\{1}-{2}.log", LogsDirectory, DateTime.Now.ToString("yyyy-MM-dd"), logType); if (!Directory.Exists(LogsDirectory)) { Directory.CreateDirectory(LogsDirectory); } if (logType == LogType.Error) { File.AppendAllText(path, string.Format("{0}{1}", Encoding.UTF8.GetString(bytes), endTag), Encoding.UTF8); } if (logType == LogType.Print) { File.AppendAllText(path, string.Format("{0}{1}", Encoding.UTF8.GetString(bytes), endTag), Encoding.UTF8); } } #endregion #region 封装方法,方便调用。 public static bool PrintWithCOM(string cmd, int port, bool isWriteLog) { PrinterType = DeviceType.COM; Port = port; IsWriteLog = isWriteLog; return PrintCommand(cmd); } public static bool PrintWithCOM(byte[] bytes, int port, bool isWriteLog) { PrinterType = DeviceType.COM; Port = port; IsWriteLog = isWriteLog; return PrintGraphics(bytes); } public static bool PrintWithLPT(string cmd, int port, bool isWriteLog) { PrinterType = DeviceType.LPT; Port = port; IsWriteLog = isWriteLog; return PrintCommand(cmd); } public static bool PrintWithLPT(byte[] bytes, int port, bool isWriteLog) { PrinterType = DeviceType.LPT; Port = port; IsWriteLog = isWriteLog; return PrintGraphics(bytes); } public static bool PrintWithTCP(string cmd, bool isWriteLog) { PrinterType = DeviceType.TCP; IsWriteLog = isWriteLog; return PrintCommand(cmd); } public static bool PrintWithTCP(byte[] bytes, bool isWriteLog) { PrinterType = DeviceType.TCP; IsWriteLog = isWriteLog; return PrintGraphics(bytes); } public static bool PrintWithDRV(string cmd, string printerName, bool isWriteLog) { PrinterType = DeviceType.DRV; PrinterName = printerName; IsWriteLog = isWriteLog; return PrintCommand(cmd); } public static bool PrintWithDRV(byte[] bytes, string printerName, bool isWriteLog) { PrinterType = DeviceType.DRV; PrinterName = printerName; IsWriteLog = isWriteLog; return PrintGraphics(bytes); } #endregion #region 打印ZPL、EPL、CPCL、TCP指令 public static bool PrintCommand(string cmd) { lock (SyncRoot) { bool result = false; try { switch (PrinterType) { case DeviceType.COM: result = comPrint(Encoding.Default.GetBytes(cmd)); break; case DeviceType.LPT: result = lptPrint(Encoding.Default.GetBytes(cmd)); break; case DeviceType.DRV: result = drvPrint(Encoding.Default.GetBytes(cmd)); break; case DeviceType.TCP: result = tcpPrint(Encoding.Default.GetBytes(cmd)); break; } if (!string.IsNullOrEmpty(cmd) && IsWriteLog) { WriteLog(cmd, LogType.Print); } } catch (Exception ex) { //记录日志 if (IsWriteLog) { WriteLog(string.Format("{0} => {1} {2}", DateTime.Now, ex.Message, ex), LogType.Error); } throw new Exception(ex.Message, ex); } finally { GraphBuffer = new byte[0]; } return result; } } #endregion #region 打印图像 public static bool PrintGraphics(byte[] graph) { lock (SyncRoot) { bool result = false; try { GraphBuffer = graph; byte[] cmdBytes = new byte[0]; switch (PrinterProgrammingLanguage) { case ProgrammingLanguage.ZPL: cmdBytes = getZPLBytes(); break; case ProgrammingLanguage.EPL: cmdBytes = getEPLBytes(); break; case ProgrammingLanguage.CPCL: cmdBytes = getCPCLBytes(); break; } switch (PrinterType) { case DeviceType.COM: result = comPrint(cmdBytes); break; case DeviceType.LPT: result = lptPrint(cmdBytes); break; case DeviceType.DRV: result = drvPrint(cmdBytes); break; case DeviceType.TCP: result = tcpPrint(cmdBytes); break; } if (cmdBytes.Length > 0 && IsWriteLog) { WriteLog(cmdBytes, LogType.Print); } } catch (Exception ex) { //记录日志 if (IsWriteLog) { WriteLog(string.Format("{0} => {1} {2}", DateTime.Now, ex.Message, ex), LogType.Error); } throw new Exception(ex.Message, ex); } finally { GraphBuffer = new byte[0]; } return result; } } #endregion #region 打印指令 private static bool drvPrint(byte[] cmdBytes) { bool result = false; try { if (!string.IsNullOrEmpty(PrinterName)) { result = WinDrvPort.SendBytesToPrinter(PrinterName, cmdBytes); } } catch (Exception ex) { throw new Exception(ex.Message, ex); } return result; } private static bool comPrint(byte[] cmdBytes) { bool result = false; SerialPort com = new SerialPort(string.Format("{0}{1}", PrinterType, Port), 9600, Parity.None, 8, StopBits.One); try { com.Open(); com.Write(cmdBytes, 0, cmdBytes.Length); result = true; } catch (Exception ex) { throw new Exception(ex.Message, ex); } finally { if (com.IsOpen) { com.Close(); } } return result; } private static bool lptPrint(byte[] cmdBytes) { return LptPort.Write(string.Format("{0}{1}", PrinterType, Port), cmdBytes); } private static bool tcpPrint(byte[] cmdBytes) { bool result = false; TcpClient tcp = null; try { tcp = TimeoutSocket.Connect(string.Empty, TcpIpAddress, TcpPort, 1000); tcp.SendTimeout = 1000; tcp.ReceiveTimeout = 1000; if (tcp.Connected) { tcp.Client.Send(cmdBytes); result = true; } } catch (Exception ex) { throw new Exception("打印失败,请检查打印机或网络设置。", ex); } finally { if (tcp != null) { if (tcp.Client != null) { tcp.Client.Close(); tcp.Client = null; } tcp.Close(); tcp = null; } } return result; } #endregion #region 生成ZPL图像打印指令 private static byte[] getZPLBytes() { byte[] bmpData = getBitmapData(); int bmpDataLength = bmpData.Length; for (int i = 0; i < bmpDataLength; i++) { bmpData[i] ^= 0xFF; } string textBitmap = string.Empty, copiesString = string.Empty; string textHex = BitConverter.ToString(bmpData).Replace("-", string.Empty); textBitmap = CompressLZ77(textHex); for (int i = 0; i < Copies; i++) { copiesString += "^XA^FO0,0^XGR:IMAGE.GRF,1,1^FS^XZ"; } string text = string.Format("~DGR:IMAGE.GRF,{0},{1},{2}{3}^IDR:IMAGE.GRF", GraphHeight * RowRealBytesCount, RowRealBytesCount, textBitmap, copiesString); return Encoding.UTF8.GetBytes(text); } #endregion #region 生成EPL图像打印指令 private static byte[] getEPLBytes() { byte[] buffer = getBitmapData(); string text = string.Format("N GW{0},{1},{2},{3},{4} P{5},1 ", 0, 0, RowRealBytesCount, GraphHeight, Encoding.GetEncoding("iso-8859-1").GetString(buffer), Copies); return Encoding.GetEncoding("iso-8859-1").GetBytes(text); } #endregion #region 生成CPCL图像打印指令 public static byte[] getCPCLBytes() { //GRAPHICS Commands //Bit-mapped graphics can be printed by using graphics commands. ASCII hex (hexadecimal) is //used for expanded graphics data (see example). Data size can be reduced to one-half by utilizing the //COMPRESSED-GRAPHICS commands with the equivalent binary character(s) of the hex data. When //using CG, a single 8 bit character is sent for every 8 bits of graphics data. When using EG two characters //(16 bits) are used to transmit 8 bits of graphics data, making EG only half as efficient. Since this data is //character data, however, it can be easier to handle and transmit than binary data. //Format: //{command} {width} {height} {x} {y} {data} //where: //{command}: Choose from the following: //EXPANDED-GRAPHICS (or EG): Prints expanded graphics horizontally. //VEXPANDED-GRAPHICS (or VEG): Prints expanded graphics vertically. //COMPRESSED-GRAPHICS (or CG): Prints compressed graphics horizontally. //VCOMPRESSED-GRAPHICS (or VCG): Prints compressed graphics vertically. //{width}: Byte-width of image. //{height} Dot-height of image. //{x}: Horizontal starting position. //{y}: Vertical starting position. //{data}: Graphics data. //Graphics command example //Input: //! 0 200 200 210 1 //EG 2 16 90 45 F0F0F0F0F0F0F0F00F0F0F0F0F0F0F0F //F0F0F0F0F0F0F0F00F0F0F0F0F0F0F0F //FORM //PRINT byte[] bmpData = getBitmapData(); int bmpDataLength = bmpData.Length; for (int i = 0; i < bmpDataLength; i++) { bmpData[i] ^= 0xFF; } string textHex = BitConverter.ToString(bmpData).Replace("-", string.Empty); string text = string.Format("! {0} {1} {2} {3} {4} EG {5} {6} {7} {8} {9} FORM PRINT ", 0, //水平偏移量 TcpPrinterDPI, //横向DPI TcpPrinterDPI, //纵向DPI (int)(TcpLabelMaxHeightCM / 2.54f * TcpPrinterDPI), //标签最大像素高度=DPI*标签纸高度(英寸) Copies, //份数 RowRealBytesCount, //图像的字节宽度 GraphHeight, //图像的像素高度 0, //横向的开始位置 0, //纵向的开始位置 textHex ); return Encoding.UTF8.GetBytes(text); } #endregion #region 获取单色位图数据 /// <summary> /// /// </summary> /// <param name="pimage"></param> /// <returns></returns> public static Bitmap ConvertToGrayscale(Bitmap pimage) { Bitmap source = null; // If original bitmap is not already in 32 BPP, ARGB format, then convert if (pimage.PixelFormat != PixelFormat.Format32bppArgb) { source = new Bitmap(pimage.Width, pimage.Height, PixelFormat.Format32bppArgb); source.SetResolution(pimage.HorizontalResolution, pimage.VerticalResolution); using (Graphics g = Graphics.FromImage(source)) { g.DrawImageUnscaled(pimage, 0, 0); } } else { source = pimage; } // Lock source bitmap in memory BitmapData sourceData = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); // Copy image data to binary array int imageSize = sourceData.Stride * sourceData.Height; byte[] sourceBuffer = new byte[imageSize]; Marshal.Copy(sourceData.Scan0, sourceBuffer, 0, imageSize); // Unlock source bitmap source.UnlockBits(sourceData); // Create destination bitmap Bitmap destination = new Bitmap(source.Width, source.Height, PixelFormat.Format1bppIndexed); // Lock destination bitmap in memory BitmapData destinationData = destination.LockBits(new Rectangle(0, 0, destination.Width, destination.Height), ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed); // Create destination buffer imageSize = destinationData.Stride * destinationData.Height; byte[] destinationBuffer = new byte[imageSize]; int sourceIndex = 0; int destinationIndex = 0; int pixelTotal = 0; byte destinationValue = 0; int pixelValue = 128; int height = source.Height; int width = source.Width; int threshold = 500; // Iterate lines for (int y = 0; y < height; y++) { sourceIndex = y * sourceData.Stride; destinationIndex = y * destinationData.Stride; destinationValue = 0; pixelValue = 128; // Iterate pixels for (int x = 0; x < width; x++) { // Compute pixel brightness (i.e. total of Red, Green, and Blue values) pixelTotal = sourceBuffer[sourceIndex + 1] + sourceBuffer[sourceIndex + 2] + sourceBuffer[sourceIndex + 3]; if (pixelTotal > threshold) { destinationValue += (byte)pixelValue; } if (pixelValue == 1) { destinationBuffer[destinationIndex] = destinationValue; destinationIndex++; destinationValue = 0; pixelValue = 128; } else { pixelValue >>= 1; } sourceIndex += 4; } if (pixelValue != 128) { destinationBuffer[destinationIndex] = destinationValue; } } // Copy binary image data to destination bitmap Marshal.Copy(destinationBuffer, 0, destinationData.Scan0, imageSize); // Unlock destination bitmap destination.UnlockBits(destinationData); // Dispose of source if not originally supplied bitmap if (source != pimage) { source.Dispose(); } // Return return destination; } /// <summary> /// 获取单色位图数据(1bpp),不含文件头、信息头、调色板三类数据。 /// </summary> /// <returns></returns> private static byte[] getBitmapData() { MemoryStream srcStream = new MemoryStream(); MemoryStream dstStream = new MemoryStream(); Bitmap srcBmp = null; Bitmap dstBmp = null; byte[] srcBuffer = null; byte[] dstBuffer = null; byte[] result = null; try { srcStream = new MemoryStream(GraphBuffer); srcBmp = Bitmap.FromStream(srcStream) as Bitmap; srcBuffer = srcStream.ToArray(); GraphWidth = srcBmp.Width; GraphHeight = srcBmp.Height; //dstBmp = srcBmp.Clone(new Rectangle(0, 0, srcBmp.Width, srcBmp.Height), PixelFormat.Format1bppIndexed); dstBmp = ConvertToGrayscale(srcBmp); dstBmp.Save(dstStream, ImageFormat.Bmp); dstBuffer = dstStream.ToArray(); int bfOffBits = BitConverter.ToInt32(dstBuffer, 10); result = new byte[GraphHeight * RowRealBytesCount]; //读取时需要反向读取每行字节实现上下翻转的效果,打印机打印顺序需要这样读取。 for (int i = 0; i < GraphHeight; i++) { Array.Copy(dstBuffer, bfOffBits + (GraphHeight - 1 - i) * RowSize, result, i * RowRealBytesCount, RowRealBytesCount); } } catch (Exception ex) { throw new Exception(ex.Message, ex); } finally { if (srcStream != null) { srcStream.Dispose(); srcStream = null; } if (dstStream != null) { dstStream.Dispose(); dstStream = null; } if (srcBmp != null) { srcBmp.Dispose(); srcBmp = null; } if (dstBmp != null) { dstBmp.Dispose(); dstBmp = null; } } return result; } #endregion #region LZ77图像字节流压缩方法 public static string CompressLZ77(string text) { //将转成16进制的文本进行压缩 string result = string.Empty; char[] arrChar = text.ToCharArray(); int count = 1; for (int i = 1; i < text.Length; i++) { if (arrChar[i - 1] == arrChar[i]) { count++; } else { result += convertNumber(count) + arrChar[i - 1]; count = 1; } if (i == text.Length - 1) { result += convertNumber(count) + arrChar[i]; } } return result; } public static string DecompressLZ77(string text) { string result = string.Empty; char[] arrChar = text.ToCharArray(); int count = 0; for (int i = 0; i < arrChar.Length; i++) { if (isHexChar(arrChar[i])) { //十六进制值 result += new string(arrChar[i], count == 0 ? 1 : count); count = 0; } else { //压缩码 int value = GetCompressValue(arrChar[i]); count += value; } } return result; } private static int GetCompressValue(char c) { int result = 0; for (int i = 0; i < compressDictionary.Count; i++) { if (c == compressDictionary[i].Key) { result = compressDictionary[i].Value; } } return result; } private static bool isHexChar(char c) { return c > 47 && c < 58 || c > 64 && c < 71 || c > 96 && c < 103; } private static string convertNumber(int count) { //将连续的数字转换成LZ77压缩代码,如000可用I0表示。 string result = string.Empty; if (count > 1) { while (count > 0) { for (int i = compressDictionary.Count - 1; i >= 0; i--) { if (count >= compressDictionary[i].Value) { result += compressDictionary[i].Key; count -= compressDictionary[i].Value; break; } } } } return result; } #endregion } } 调用例子代码: private void BackgroundWorkerPrint_DoWork(object sender, DoWorkEventArgs e) { BackgroundWorker worker = sender as BackgroundWorker; int i = 0, nextRemainder = 0, count = this._listBarcodeData.Count; bool flag = true; float pageWidth, pageHeight; int dpiX, dpiY, perPaperFactor; string reportPath = string.Format(@"{0}/Reports/{1}", Application.StartupPath, this._modelType); PrintLog printLog = new PrintLog() { Operater = LoginName }; PrinterSettings printerSettings = new PrinterSettings() { PrinterName = PrintParam, Copies = 1 }; using (StreamReader tr = new StreamReader(this.ModelFilePath)) { XElement xe = XDocument.Load(tr).Root.Elements() .Elements(XName.Get("ModelType")).First(x => x.Value == this._modelType).Parent; pageWidth = float.Parse(xe.Elements(XName.Get("PageWidth")).First().Value); pageHeight = float.Parse(xe.Elements(XName.Get("PageHeight")).First().Value); dpiX = int.Parse(xe.Elements(XName.Get("DotPerInchX")).First().Value); dpiY = int.Parse(xe.Elements(XName.Get("DotPerInchY")).First().Value); perPaperFactor = int.Parse(xe.Elements(XName.Get("PerPaperFactor")).First().Value); this._no = int.Parse(xe.Elements(XName.Get("NO")).First().Value); } using (LocalReportHelper printHelper = new LocalReportHelper(reportPath)) { printHelper.PrintTypeNO = this._no; printHelper.PrintLogInformation = printLog; printHelper.ExportImageDeviceInfo.DpiX = dpiX; printHelper.ExportImageDeviceInfo.DpiY = dpiY; printHelper.ExportImageDeviceInfo.PageWidth = pageWidth; printHelper.ExportImageDeviceInfo.PageHeight = pageHeight; foreach (BarcodeData bdCurrent in this._listBarcodeData) { if (worker.CancellationPending == true) { e.Cancel = true; break; } else { try { DataSet dsCurrent = this.GetDataForPrinterByBarcode(bdCurrent.Barcode, bdCurrent.IncreaseType); DataSet dsNext = null, dsPrevious = dsCurrent.Copy(); int amount = this._printType == 0 ? 1 : bdCurrent.Amount - nextRemainder; int copies = amount / perPaperFactor; int remainder = nextRemainder = amount % perPaperFactor; Action<DataSet, int, string, int> actPrint = (ds, duplicates, barcodes, amountForLog) => { printHelper.PrintLogInformation.Barcode = barcodes; printHelper.PrintLogInformation.Amount = amountForLog; if (this.PrintType == 0 && DeviceType == DeviceType.DRV) { printerSettings.Copies = (short)duplicates; printHelper.WindowsDriverPrint(printerSettings, dpiX, ds); } else { printHelper.OriginalPrint(DeviceType, ds, duplicates, PrintParam); } }; if (copies > 0) { int amountForCopy = copies; if (perPaperFactor > 1) { DataSet dsCurrentCopy = dsCurrent.CopyForBarcode(); dsCurrent.Merge(dsCurrentCopy); amountForCopy = copies * perPaperFactor; } actPrint.Invoke(dsCurrent, copies, bdCurrent.Barcode, amountForCopy); } if (remainder > 0) { int nextIndex = i + 1; string barcodes = bdCurrent.Barcode; if (nextIndex < count) { BarcodeData bdNext = this._listBarcodeData[nextIndex]; dsNext = this.GetDataForPrinterByBarcode(bdNext.Barcode, bdNext.IncreaseType); dsPrevious.Merge(dsNext); barcodes += "," + bdNext.Barcode; } actPrint.Invoke(dsPrevious, 1, barcodes, 1); } worker.ReportProgress(i++, string.Format("正在生成 {0} 并输送往打印机...", bdCurrent.Barcode)); if (this._printType == 0) { count = 1; flag = true; break; } } catch (Exception ex) { flag = false; e.Result = ex.Message; break; } } } if (!e.Cancel && flag) { e.Result = string.Format("打印操作成功完成,共处理条码 {0} 条", count); } } } LocalReportHelper类代码: using System; using System.Configuration; using System.Data; using System.Drawing; using System.Drawing.Imaging; using System.Drawing.Printing; using System.IO; using System.Text; using System.Windows.Forms; using Microsoft.Reporting.WinForms; using Umisky.BarcodePrint.Core; namespace Umisky.BarcodePrint.Codes { public class LocalReportHelper : IDisposable { #region Properties public String LocalReportPath { get; set; } public LocalReport LocalReportInstance { get; private set; } public GraphDeviceInfo ExportImageDeviceInfo { get; set; } public PrintLog PrintLogInformation { get; set; } public int PrintTypeNO { get; set; } #endregion private Stream _stream; private int _bmpDPI; private DataSet _ds; public LocalReportHelper(String reportPath) : this(reportPath, new GraphDeviceInfo() { ColorDepth = 1, DpiX = 203, DpiY = 203, PageWidth = 8f, PageHeight = 12.2f, MarginTop = 0.2f }) { } public LocalReportHelper(String reportPath, GraphDeviceInfo deviceInfo) { this._bmpDPI = 96; this.LocalReportPath = reportPath; this.ExportImageDeviceInfo = deviceInfo; this.LocalReportInstance = new LocalReport() { ReportPath = reportPath }; this.LocalReportInstance.SubreportProcessing += new SubreportProcessingEventHandler(LocalReportInstance_SubreportProcessing); } private void LocalReportInstance_SubreportProcessing(object sender, SubreportProcessingEventArgs e) { foreach (DataTable dt in this._ds.Tables) { e.DataSources.Add(new ReportDataSource(dt.TableName, dt)); } } public void Dispose() { this.ExportImageDeviceInfo = null; this.LocalReportInstance = null; this.LocalReportPath = null; this._ds = null; } public void AddReportParameter(string paramName, string value) { this.LocalReportInstance.SetParameters(new ReportParameter(paramName, value)); } #region Export hang title image by reporting services private void AddWashIcones() { this.LocalReportInstance.EnableExternalImages = true; this.LocalReportInstance.SetParameters(new ReportParameter("AppPath", Application.StartupPath)); } private void AddBarcodesAssembly() { this.LocalReportInstance.AddTrustedCodeModuleInCurrentAppDomain(ConfigurationManager.AppSettings["BarcodesAssembly"]); } private Stream CreateStreamCallBack(string name, string fileNameExtension, Encoding encoding, string mimeType, bool willSeek) { string tempFolderPath = string.Concat(Environment.GetEnvironmentVariable("TEMP"), "/"); this._stream = new FileStream(string.Concat(tempFolderPath, name, ".", fileNameExtension), FileMode.Create); return this._stream; } private void Export() { if (string.IsNullOrEmpty(this.LocalReportPath) || this.LocalReportInstance == null || this.ExportImageDeviceInfo == null) { throw new InvalidExpressionException("Invalid parameters"); } if (this.PrintTypeNO >= -1 || this.PrintTypeNO == -3) { this.AddBarcodesAssembly(); if (this.PrintTypeNO >= 0) { this.AddWashIcones(); } } if (this.PrintTypeNO >= 0) { this.LocalReportInstance.DataSources.Clear(); foreach (DataTable dt in this._ds.Tables) { this.LocalReportInstance.DataSources.Add(new ReportDataSource(dt.TableName, dt)); } } this.LocalReportInstance.Refresh(); if (this._stream != null) { this._stream.Close(); this._stream = null; } Warning[] warnings; this.LocalReportInstance.Render( "Image", this.ExportImageDeviceInfo.ToString(), PageCountMode.Actual, CreateStreamCallBack, out warnings); this._stream.Position = 0; } private void SaveLog() { using (Bitmap image = (Bitmap)Image.FromStream(this._stream)) { image.SetResolution(96, 96); using (MemoryStream ms = new MemoryStream()) { image.Save(ms, ImageFormat.Jpeg); this.PrintLogInformation.BarcodeImage = ms.ToArray(); } } LogHelper.AddLog(this.PrintLogInformation); if (this._stream != null) { this._stream.Close(); this._stream = null; } } #endregion #region Windows driver print private void PrintPage(object sender, PrintPageEventArgs ev) { Bitmap bmp = (Bitmap)Image.FromStream(this._stream); bmp.SetResolution(this._bmpDPI, this._bmpDPI); ev.Graphics.DrawImage(bmp, 0, 0); ev.HasMorePages = false; } /// <summary> /// Print by windows driver /// </summary> /// <param name="printerSettings">.net framework PrinterSettings class, including some printer information</param> /// <param name="bmpDPI">the bitmap image resoluation, dots per inch</param> public void WindowsDriverPrint(PrinterSettings printerSettings, int bmpDPI, DataSet ds) { this._ds = ds; this.Export(); if (this._stream == null) { return; } this._bmpDPI = bmpDPI; PrintDocument printDoc = new PrintDocument(); printDoc.DocumentName = "条码打印"; printDoc.PrinterSettings = printerSettings; printDoc.PrintController = new StandardPrintController(); if (!printDoc.PrinterSettings.IsValid) { if (this._stream != null) { this._stream.Close(); this._stream = null; } MessageBox.Show("Printer found errors, Please contact your administrators!", "Print Error"); return; } printDoc.PrintPage += new PrintPageEventHandler(PrintPage); printDoc.Print(); this.SaveLog(); } #endregion #region Original print /// <summary> /// Send the file to the printer or use the printer command /// </summary> /// <param name="deviceType">The port(LPT,COM,DRV) which the device connecting</param> /// <param name="copies">Total number for print</param> /// <param name="ds">The report datasource</param> /// <param name="printParam">Print parameters</param> /// <param name="printLanguage">The built-in printer programming language, you can choose EPL or ZPL</param> public void OriginalPrint(DeviceType deviceType, DataSet ds, int copies = 1, string printParam = null, ProgrammingLanguage printLanguage = ProgrammingLanguage.ZPL) { this._ds = ds; this.Export(); if (this._stream == null) { return; } int port = 1; int.TryParse(printParam, out port); int length = (int)this._stream.Length; byte[] bytes = new byte[length]; this._stream.Read(bytes, 0, length); ZebraPrintHelper.Copies = copies; ZebraPrintHelper.PrinterType = deviceType; ZebraPrintHelper.PrinterName = printParam; ZebraPrintHelper.Port = port; ZebraPrintHelper.PrinterProgrammingLanguage = printLanguage; ZebraPrintHelper.PrintGraphics(bytes); this.SaveLog(); } #endregion } }
效果:
6.C#调用斑马打印机打印条码标签(支持COM、LPT、USB、TCP连接方式和ZPL、EPL、CPCL指令)
// 搬运来源: https://www.cnblogs.com/chengeng/p/6136185.html // Printer IP Address and communication port string ipAddress = "10.3.14.42"; int port = 9100; // ZPL Command(s) string ZPLString = "^XA" + "^FO50,50" + "^A0N50,50" + "^FDHello, World!^FS" + "^XZ"; try { // Open connection System.Net.Sockets.TcpClient client = new System.Net.Sockets.TcpClient(); client.Connect(ipAddress, port); // Write ZPL String to connection System.IO.StreamWriter writer = new System.IO.StreamWriter(client.GetStream()); writer.Write(ZPLString); writer.Flush(); // Close Connection writer.Close(); client.Close(); } catch (Exception ex) { // Catch Exception }
7.C#通过命令发送的方式,实现斑马打印机zpl命令打印
搬运来源: https://blog.csdn.net/yfy9528/article/details/100989046?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param
效果:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; using System.IO; namespace Printer1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void btn_print_Click(object sender, EventArgs e) { PrintZPL(txt_zpl.Text); } public bool PrintZPL(string zpl) { return RawPrinterHelper.SendStringToPrinter("ZDesigner ZT210-300dpi ZPL", zpl); } public class RawPrinterHelper { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct DOCINFOW { [MarshalAs(UnmanagedType.LPWStr)] public string pDocName; [MarshalAs(UnmanagedType.LPWStr)] public string pOutputFile; [MarshalAs(UnmanagedType.LPWStr)] public string pDataType; } [DllImport("winspool.Drv", EntryPoint = "OpenPrinterW", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)] public static extern bool OpenPrinter(string src, ref IntPtr hPrinter, long pd); [DllImport("winspool.Drv", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)] public static extern bool ClosePrinter(IntPtr hPrinter); [DllImport("winspool.Drv", EntryPoint = "StartDocPrinterW", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)] public static extern bool StartDocPrinter(IntPtr hPrinter, int level, ref RawPrinterHelper.DOCINFOW pDI); [DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] public static extern bool EndDocPrinter(IntPtr hPrinter); [DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] public static extern bool StartPagePrinter(IntPtr hPrinter); [DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] public static extern bool EndPagePrinter(IntPtr hPrinter); [DllImport("winspool.Drv", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)] public static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, int dwCount, ref int 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. public static bool SendBytesToPrinter(string szPrinterName, IntPtr pBytes, Int32 dwCount) { bool bSuccess = false; // Assume failure unless you specifically succeed. Int32 dwError = 0, dwWritten = 0; IntPtr hPrinter = System.IntPtr.Zero;// new IntPtr(0); DOCINFOW di = new DOCINFOW(); di.pDocName = DateTime.Now.ToString("yyyymmddhhMMss") + DateTime.Now.Millisecond.ToString(); //"My C#.NET RAW Document"; di.pDataType = "RAW"; di.pOutputFile = null; // Open the printer..nNormalize() if (OpenPrinter(szPrinterName, ref hPrinter, 0)) { // Start a document. if (StartDocPrinter(hPrinter, 1, ref di)) { // Start a page. if (StartPagePrinter(hPrinter)) { // Write your bytes. bSuccess = WritePrinter(hPrinter, pBytes, dwCount, ref 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; } public static bool SendFileToPrinter(string szPrinterName, string szFileName) { bool bSuccess = false; // Open the file. FileStream fs = new FileStream(szFileName, FileMode.Open); try { // Create a BinaryReader on the file. BinaryReader br = new BinaryReader(fs, System.Text.Encoding.Default); // Dim an array of bytes big enough to hold the file's contents. Byte[] bytes = new Byte[fs.Length]; // 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; } catch (Exception ex) { MessageBox.Show(ex.Message); return bSuccess; } finally { if (fs != null) { fs.Close(); } } } public static bool SendStringToPrinter(string szPrinterName, string szString) { IntPtr pBytes; Int32 dwCount; // How many characters are in the string? dwCount = szString.Length; // Assume that the printer is expecting ANSI text, and then convert // the string to ANSI text. pBytes = Marshal.StringToCoTaskMemAnsi(szString); // Send the converted ANSI string to the printer. SendBytesToPrinter(szPrinterName, pBytes, dwCount); Marshal.FreeCoTaskMem(pBytes); return true; } } }
8.C# 简单的ZEBRA标签打印程序
搬运出处: https://blog.csdn.net/jianmtao/article/details/7324351?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param Zebra打印机有专用的的语言ZPL,简单的使用C#编程打印方法: 1. 写ZPL脚本,定义好相关打印格式,数据名,等,此保存为txt格式即可 脚本可以用BARONE5.0程序生成, 2. 通过C#程序,操作脚本txt文件,将需要打印的数据替换进脚本 C#如何操作txt,简单的不要再说了 3. 将此脚本通过DOS copy的方法,直接copy到ZEBRA的LPT口即可 //将脚本送到打印口 Process cmd = new Process(); cmd.StartInfo.FileName = "cmd.exe"; cmd.StartInfo.Arguments = "/c copy script-go.txt LPT1 "; cmd.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; cmd.Start(); while (true) { if (cmd.HasExited) { break; } System.Threading.Thread.Sleep(400); }
完整实例:
打印标签,替换4点为1点,通过code取得名称,etc
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Data.OleDb; using System.IO; using System.Diagnostics; namespace LabelPrint { public partial class Main : Form { public Main() { InitializeComponent(); //using skin Sunisoft.IrisSkin.SkinEngine MySkin; MySkin = new Sunisoft.IrisSkin.SkinEngine(this); MySkin.SkinFile = "MacOS.ssk"; } //产生脚本的函数,将script内代码读取,参数替换,并生成新的script-go.txt private string ScriptStr, F_ScriptStr; private void ScriptGen() { StreamReader SR = new StreamReader("script.txt"); ScriptStr = SR.ReadToEnd(); SR.Close(); F_ScriptStr = ScriptStr.Replace("$sn$", F_SN); F_ScriptStr = F_ScriptStr.Replace("$itemcode$", F_IC); F_ScriptStr = F_ScriptStr.Replace("$itemname$", F_IN); //得到修改后的字符串F_ScriptStr //生成新的txt文件 File.Delete("script-go.txt"); StreamWriter SW = new StreamWriter("script-go.txt", true); SW.Write(F_ScriptStr); SW.Close(); } //输入框内的SN,输入框内的ItemCode,最终SN,最终ItemCode,最终ItemName private string SN, IC, F_SN, F_IC, F_IN; private void buttonPrint_Click_1(object sender, EventArgs e) { SN = textBoxSN.Text; IC = textBoxCode.Text; int SN_Len, IC_Len; SN_Len = SN.Length; IC_Len = IC.Length; //判断输入框内是否输入数据,数据位数是否正确 if (SN_Len != 11) { MessageBox.Show("! Wrong : Please check the SN"); textBoxSN.Focus(); textBoxSN.SelectAll(); return; } if (IC_Len < 11) { MessageBox.Show("! Wrong : Please check the itemcode"); textBoxCode.Focus(); textBoxCode.SelectAll(); return; } //取出Itemcode的“4点” string F_IC1, F_IC2; F_SN = SN; F_IC1 = IC.Substring(0, 8);//已经包含"." switch (IC_Len) { case 11: F_IC2 = IC.Substring(8, 3); F_IC = F_IC1 + F_IC2; break; case 12: F_IC2 = IC.Substring(8, 4); F_IC = F_IC1 + F_IC2; break; case 14: F_IC2 = IC.Substring(11, 3); F_IC = F_IC1 + F_IC2; break; case 15: F_IC2 = IC.Substring(11, 4); F_IC = F_IC1 + F_IC2; break; default: MessageBox.Show("! Wrong : Please check the itemcode"); textBoxCode.Focus(); textBoxCode.SelectAll(); break; } //这里已经得到最终的 F_SN 和 F_IC //下面连接数据库,核对输入的F_IC,得到对应的ItemName, F_IN string Connstr = "Provider = Microsoft.Jet.OLEDB.4.0; Jet OLEDB:Database Password=rctool;Data Source = convert.mdb"; OleDbConnection Conn = new OleDbConnection(Connstr); Conn.Open(); string CMDStr = "SELECT * FROM cvn WHERE code='" + F_IC + "'"; OleDbCommand CMD = new OleDbCommand(CMDStr, Conn); OleDbDataReader dr = CMD.ExecuteReader(); if (dr.HasRows == false) { MessageBox.Show("This code doesn't exist in database"); Conn.Close(); textBoxCode.Focus(); textBoxCode.SelectAll(); return; } if (dr.HasRows == true) { dr.Read(); F_IN = dr["name"].ToString(); Conn.Close(); } //这里已经得到最终的 F_IN //至此F_SN,F_IC,F_IN已经全部得到 //下面开始输出这些参数,生成新的打印脚本script-go.txt,脚本默认产生在程序目录下面 ScriptGen(); //下面将此脚本送到打印口 Process cmd = new Process(); cmd.StartInfo.FileName = "cmd.exe"; cmd.StartInfo.Arguments = "/c copy script-go.txt LPT1 "; cmd.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; cmd.Start(); while (true) { if (cmd.HasExited) { break; } System.Threading.Thread.Sleep(400); } textBoxCode.Clear(); textBoxSN.Focus(); textBoxSN.SelectAll(); } } }
9.在发送给Zebra打印机之前,使用.NET WinForm打印预览ZPL II命令
我有一个.NET Windows应用程序,使用ZPL II或EPL2向Zebra打印机打印命令.
在直接从Zebra打印机打印之前,是否有任何方式打印预览表格中的数据?
在直接从Zebra打印机打印之前,是否有任何方式打印预览表格中的数据?
看看 Labelary web service,它允许您以编程方式将ZPL转换为图像.
View Code
只需构建一个包含您要呈现的ZPL的URL,从Web服务器获取图像,并从应用程序中向用户显示图像.
string zpl = "YOUR ZPL HERE"; string url = "http://api.labelary.com/v1/printers/8dpmm/labels/4x6/0/" + zpl; using (WebClient client = new WebClient()) { client.DownloadFile(url, "zpl.png"); }
10.把图像转换成斑马打印机的命令
using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; namespace EHX.QrCode { /// <summary> /// 斑马工具类,把图像转换成斑马打印机的命令 /// </summary> public class ZebraUnity { #region 定义私有字段 /// <summary> /// 线程锁,防止多线程调用。 /// </summary> private static object SyncRoot = new object(); /// <summary> /// ZPL压缩字典 /// </summary> private static List<KeyValuePair<char, int>> compressDictionary = new List<KeyValuePair<char, int>>(); #endregion #region 构造方法 static ZebraUnity() { InitCompressCode(); } #endregion #region 定义属性 /// <summary> /// 图像的二进制数据 /// </summary> public static byte[] GraphBuffer { get; set; } /// <summary> /// 图像的宽度 /// </summary> private static int GraphWidth { get; set; } /// <summary> /// 图像的高度 /// </summary> private static int GraphHeight { get; set; } private static int RowSize { get { return (((GraphWidth) + 31) >> 5) << 2; } } /// <summary> /// 每行的字节数 /// </summary> private static int RowRealBytesCount { get { if ((GraphWidth % 8) > 0) { return GraphWidth / 8 + 1; } else { return GraphWidth / 8; } } } #endregion #region 位图转斑马指令字符串 /// <summary> /// 位图转斑马指令字符串 /// </summary> /// <param name="bitmap">位图数据</param> /// <param name="totalBytes">总共的字节数</param> /// <param name="rowBytes">每行的字节数</param> /// <returns>斑马ZPL 2命令</returns> public static string BmpToZpl(byte[] bitmap, out int totalBytes, out int rowBytes) { try { GraphBuffer = bitmap; byte[] bmpData = getBitmapData(); string textHex = BitConverter.ToString(bmpData).Replace("-", string.Empty); string textBitmap = CompressLZ77(textHex); totalBytes = GraphHeight * RowRealBytesCount; rowBytes = RowRealBytesCount; return textBitmap; } catch (Exception ex) { throw ex; } } /// <summary> /// 位图转ZPL指令 /// </summary> /// <param name="bitmap">位图</param> /// <param name="totalBytes">返回参数总共字节数</param> /// <param name="rowBytes">返回参数每行的字节数</param> /// <returns>ZPL命令</returns> public static string BmpToZpl(Image bitmap, out int totalBytes, out int rowBytes) { using (MemoryStream stream = new MemoryStream()) { bitmap.Save(stream, ImageFormat.Bmp); return BmpToZpl(stream.ToArray(), out totalBytes, out rowBytes); } } /// <summary> /// 根据图片生成图片的ASCII 十六进制 /// </summary> /// <param name="sourceBmp">原始图片</param> /// <param name="totalBytes">总共字节数</param> /// <param name="rowBytes">每行的字节数</param> /// <returns>ASCII 十六进制</returns> public static string BitmapToHex(Image sourceBmp, out int totalBytes, out int rowBytes) { // 转成单色图 Bitmap grayBmp = ConvertToGrayscale(sourceBmp as Bitmap); // 锁定位图数据 Rectangle rect = new Rectangle(0, 0, grayBmp.Width, grayBmp.Height); System.Drawing.Imaging.BitmapData bmpData = grayBmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, grayBmp.PixelFormat); // 获取位图数据第一行的起始地址 IntPtr ptr = bmpData.Scan0; // 定义数组以存放位图的字节流数据 // 处理像素宽对应的字节数,如不为8的倍数,则对最后一个字节补0 int width = (int)Math.Ceiling(grayBmp.Width / 8.0); // 获取位图实际的字节宽,这个值因为要考虑4的倍数关系,可能大于width int stride = Math.Abs(bmpData.Stride); // 计算位图数据实际所占的字节数,并定义数组 int bitmapDataLength = stride * grayBmp.Height; byte[] ImgData = new byte[bitmapDataLength]; // 从位图文件复制图像数据到数组,从实际图像数据的第一行开始;因ptr指针而无需再考虑行倒序存储的处理 System.Runtime.InteropServices.Marshal.Copy(ptr, ImgData, 0, bitmapDataLength); // 计算异或操作数,以处理包含图像数据但又有补0操作的那个字节 byte mask = 0xFF; // 计算这个字节补0的个数 //int offset = 8 * width - grayBmp.Width; int offset = 8 - (grayBmp.Width % 8); //offset %= 8; offset = offset % 8; // 按补0个数对0xFF做相应位数的左移位操作 mask <<= (byte)offset; // 图像反色处理 for (int j = 0; j < grayBmp.Height; j++) { for (int i = 0; i < stride; i++) { if (i < width - 1) //无补0的图像数据 { ImgData[j * stride + i] ^= 0xFF; } else if (i == width - 1) //有像素的最后一个字节,可能有补0 { ImgData[j * stride + i] ^= mask; } else //为满足行字节宽为4的倍数而最后补的字节 { //ImgData[j * stride + i] = 0x00; ImgData[j * stride + i] ^= 0x00; } } } // 将位图数据转换为16进制的ASCII字符 string zplString = BitConverter.ToString(ImgData); zplString = CompressLZ77(zplString.Replace("-", string.Empty)); totalBytes = bitmapDataLength; rowBytes = stride; return zplString; } #endregion #region 获取单色位图数据 /// <summary> /// 获取单色位图数据 /// </summary> /// <param name="pimage"></param> /// <returns></returns> private static Bitmap ConvertToGrayscale(Bitmap pimage) { Bitmap source = null; // If original bitmap is not already in 32 BPP, ARGB format, then convert if (pimage.PixelFormat != PixelFormat.Format32bppArgb) { source = new Bitmap(pimage.Width, pimage.Height, PixelFormat.Format32bppArgb); source.SetResolution(pimage.HorizontalResolution, pimage.VerticalResolution); using (Graphics g = Graphics.FromImage(source)) { g.DrawImageUnscaled(pimage, 0, 0); } } else { source = pimage; } // Lock source bitmap in memory BitmapData sourceData = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); // Copy image data to binary array int imageSize = sourceData.Stride * sourceData.Height; byte[] sourceBuffer = new byte[imageSize]; Marshal.Copy(sourceData.Scan0, sourceBuffer, 0, imageSize); // Unlock source bitmap source.UnlockBits(sourceData); // Create destination bitmap Bitmap destination = new Bitmap(source.Width, source.Height, PixelFormat.Format1bppIndexed); // Lock destination bitmap in memory BitmapData destinationData = destination.LockBits(new Rectangle(0, 0, destination.Width, destination.Height), ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed); // Create destination buffer imageSize = destinationData.Stride * destinationData.Height; byte[] destinationBuffer = new byte[imageSize]; int sourceIndex = 0; int destinationIndex = 0; int pixelTotal = 0; byte destinationValue = 0; int pixelValue = 128; int height = source.Height; int width = source.Width; int threshold = 500; // Iterate lines for (int y = 0; y < height; y++) { sourceIndex = y * sourceData.Stride; destinationIndex = y * destinationData.Stride; destinationValue = 0; pixelValue = 128; // Iterate pixels for (int x = 0; x < width; x++) { // Compute pixel brightness (i.e. total of Red, Green, and Blue values) pixelTotal = sourceBuffer[sourceIndex + 1] + sourceBuffer[sourceIndex + 2] + sourceBuffer[sourceIndex + 3]; if (pixelTotal > threshold) { destinationValue += (byte)pixelValue; } if (pixelValue == 1) { destinationBuffer[destinationIndex] = destinationValue; destinationIndex++; destinationValue = 0; pixelValue = 128; } else { pixelValue >>= 1; } sourceIndex += 4; } if (pixelValue != 128) { destinationBuffer[destinationIndex] = destinationValue; } } // Copy binary image data to destination bitmap Marshal.Copy(destinationBuffer, 0, destinationData.Scan0, imageSize); // Unlock destination bitmap destination.UnlockBits(destinationData); // Dispose of source if not originally supplied bitmap if (source != pimage) { source.Dispose(); } // Return return destination; } /// <summary> /// 获取单色位图数据(1bpp),不含文件头、信息头、调色板三类数据。 /// </summary> /// <returns></returns> private static byte[] getBitmapData() { MemoryStream srcStream = new MemoryStream(); MemoryStream dstStream = new MemoryStream(); Bitmap srcBmp = null; Bitmap dstBmp = null; byte[] srcBuffer = null; byte[] dstBuffer = null; byte[] result = null; try { srcStream = new MemoryStream(GraphBuffer); srcBmp = Bitmap.FromStream(srcStream) as Bitmap; srcBuffer = srcStream.ToArray(); GraphWidth = srcBmp.Width; GraphHeight = srcBmp.Height; //dstBmp = srcBmp.Clone(new Rectangle(0, 0, srcBmp.Width, srcBmp.Height), PixelFormat.Format1bppIndexed); dstBmp = ConvertToGrayscale(srcBmp); dstBmp.Save(dstStream, ImageFormat.Bmp); dstBuffer = dstStream.ToArray(); result = dstBuffer; int bfOffBits = BitConverter.ToInt32(dstBuffer, 10); result = new byte[GraphHeight * RowRealBytesCount]; ////读取时需要反向读取每行字节实现上下翻转的效果,打印机打印顺序需要这样读取。 for (int i = 0; i < GraphHeight; i++) { int sindex = bfOffBits + (GraphHeight - 1 - i) * RowSize; int dindex = i * RowRealBytesCount; Array.Copy(dstBuffer, sindex, result, dindex, RowRealBytesCount); } for (int i = 0; i < result.Length; i++) { result[i] ^= 0xFF; } } catch (Exception ex) { throw new Exception(ex.Message, ex); } finally { if (srcStream != null) { srcStream.Dispose(); srcStream = null; } if (dstStream != null) { dstStream.Dispose(); dstStream = null; } if (srcBmp != null) { srcBmp.Dispose(); srcBmp = null; } if (dstBmp != null) { dstBmp.Dispose(); dstBmp = null; } } return result; } #endregion #region LZ77图像字节流压缩方法 private static string CompressLZ77(string text) { //将转成16进制的文本进行压缩 string result = string.Empty; char[] arrChar = text.ToCharArray(); int count = 1; for (int i = 1; i < text.Length; i++) { if (arrChar[i - 1] == arrChar[i]) { count++; } else { result += convertNumber(count) + arrChar[i - 1]; count = 1; } if (i == text.Length - 1) { result += convertNumber(count) + arrChar[i]; } } return result; } private static string DecompressLZ77(string text) { string result = string.Empty; char[] arrChar = text.ToCharArray(); int count = 0; for (int i = 0; i < arrChar.Length; i++) { if (isHexChar(arrChar[i])) { //十六进制值 result += new string(arrChar[i], count == 0 ? 1 : count); count = 0; } else { //压缩码 int value = GetCompressValue(arrChar[i]); count += value; } } return result; } private static int GetCompressValue(char c) { int result = 0; for (int i = 0; i < compressDictionary.Count; i++) { if (c == compressDictionary[i].Key) { result = compressDictionary[i].Value; } } return result; } private static bool isHexChar(char c) { return c > 47 && c < 58 || c > 64 && c < 71 || c > 96 && c < 103; } private static string convertNumber(int count) { //将连续的数字转换成LZ77压缩代码,如000可用I0表示。 string result = string.Empty; if (count > 1) { while (count > 0) { for (int i = compressDictionary.Count - 1; i >= 0; i--) { if (count >= compressDictionary[i].Value) { result += compressDictionary[i].Key; count -= compressDictionary[i].Value; break; } } } } return result; } private static void InitCompressCode() { //G H I J K L M N O P Q R S T U V W X Y 对应1,2,3,4……18,19。 //g h i j k l m n o p q r s t u v w x y z 对应20,40,60,80……340,360,380,400。 for (int i = 0; i < 19; i++) { compressDictionary.Add(new KeyValuePair<char, int> (Convert.ToChar(71 + i), i + 1 )); } for (int i = 0; i < 20; i++) { compressDictionary.Add(new KeyValuePair<char, int>(Convert.ToChar(103 + i), (i + 1) * 20)); } } #endregion } }
11.网络打印 C#代码
// Printer IP Address and communication port string ipAddress = "10.3.14.42"; int port = 9100; // ZPL Command(s) string ZPLString = "^XA" + "^FO50,50" + "^A0N50,50" + "^FDHello, World!^FS" + "^XZ"; try { // Open connection System.Net.Sockets.TcpClient client = new System.Net.Sockets.TcpClient(); client.Connect(ipAddress, port); // Write ZPL String to connection System.IO.StreamWriter writer = new System.IO.StreamWriter(client.GetStream()); writer.Write(ZPLString); writer.Flush(); // Close Connection writer.Close(); client.Close(); } catch (Exception ex) { // Catch Exception }