新项目要用斑马打印机打标签, 之前做过一个是用FastReport 设计好标签模板,调用 FastReport的dll就能打印了. 可以查看这个 用BarTender Vs FastReport 打印二维码 比较
现在还没拿到打印机, 拿到之后,可以首先尝试FastReport是否可以用, 这样是最省时间了. 实在不想折腾ZPL, 这种不是可视化的.标签内容一多,就没法看了.
斑马打印机安装不能用USB延长线,也不能插前面的USB口,只有插上去在设备管理器里的USB里找到USB打印支持,才能安装成功
Page description language – ZPL
ZPL-Zebra编程语言-打印页面的描述语言,也称为PDL(页面描述语言)。有许多PDL。几乎每个打印机制造商都有其自己的页面描述语言。该语言使您可以通过高级命令来描述页面,打印机将以高级命令来解释页面。最著名的PDL是Adobe的PostScript。 PDL允许描述页面对象。有一些东西使程序独立于打印机的特定硬件平台。打印机收到用于打印正方形,符号或线条的命令,我们不在乎如何实现。打印机本身知道如何执行此操作。这是PDL的主要优势。
美国“ Zebra Technologies”公司开发了ZPL,主要用于标签的创建和打印。标签可以包含文本,条形码和简单图形。此类标签使用特殊的Zebra打印机打印,该打印机在行业中用于打印收据和支票。
现在有两个标准:ZPL和ZPL ll
差异
开发ZPL II的主要原因是大大减少了打印机开始接收数据和打印第一个字符的时间。这主要是通过更改ZPL程序的编写方式来实现的。
ZPL II标准与ZPL标准不是100%兼容。但是两者之间的差异很小。 ZPL上的所有程序都可以轻松地修改为ZPL ll的级别。向后兼容。也就是说,当然可以考虑到旧语法在ZPL打印机上的ZPL ll上编写程序。
因此,这是ZPL ll和ZPL之间的两个主要区别:
1.在ZPL II中,数据在接收后立即格式化。并且在ZPL标准中,直到您获得命令以完成流程格式化^ XZ时,格式化才会开始。
2. ZPL ll有很多新命令。
Syntax语法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
^XA ^FX 带有公司徽标,名称和地址的顶部 ^CF0,60 ^FO55,55^GC100^FS ^FO75,55^GC100^FS ^FO75,75^GC100^FS ^FO55,75^GC100^FS ^FO88,88^GC50,50^FS ^FO220,50^FDLorem Ipsum, Inc.^FS ^CF0,40 ^FO220,100^FD1000 Shipping Lane^FS ^FO220,135^FDShelbyville TN 38102^FS ^FO220,170^FDEURO UNION (EU)^FS ^FO50,250^GB700,1,3^FS ^FX 第二部分包含收件人地址和许可证信息 ^CFA,30 ^FO50,300^FDKarl Marks^FS ^FO50,340^FD100 Main Street^FS ^FO50,380^FDEURO UNION (EU)^FS ^CFA,15 ^FO50,450^GB700,1,3^FS ^FX 第三部分,带条形码 ^BY5,2,120 ^FO175,500^BC^FD1234567890^FS ^FX 第四部分(底部的两个框)。 ^FO50,700^GB700,250,3^FS ^FO400,700^GB1,250,3^FS ^CF0,40 ^FO100,760^FDShipping Ctr. Y74H-1^FS ^FO100,800^FDREF1 F99L17^FS ^FO100,840^FDREF2 YUH88^FS ^CF0,190 ^FO485,765^FDAA^FS ^XZ |
打印出来的标签样式
代码以标签(命令)^ XA开头,并以标签^ XZ结尾。
1) The first section displays the company logo and its legal data:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
^FX Top section with company logo, name and address. ^CF0,60 ^FO55,55^GC100^FS ^FO75,55^GC100^FS ^FO75,75^GC100^FS ^FO55,75^GC100^FS ^FO88,88^GC50,50^FS ^FO220,50^FDLorem Ipsum, Inc.^FS ^CF0,40 ^FO220,100^FD1000 Shipping Lane^FS ^FO220,135^FDShelbyville TN 38102^FS ^FO220,170^FDEURO UNION (EU)^FS ^FO50,250^GB700,1,3^FS |
标记 ^ FX表示注释。
^CF x, y, z – 默认字体设置:字体,高度和宽度。
^FO x,y 左和上缩进。
^FS – 行尾。
用4个圆圈组成一个LOGO
^GC x,y – draw a circle. Diameter – x, line thickness – y.
Legal data:
^FD – data field.
2)在第二部分中,我们将不会看到新标签。
3)在第三部分中,添加条形码:
1 2 3 |
^FX Third section with barcode. ^BY5,2,120 ^FO175,500^BC^FD1234567890^FS |
Here:
^BY x,y,z – 条码宽度,高度
4) 第四部分,长方形框
^GB x,y,z – rectangle (box). Width, height, thickness of the frame.
通过使用一小组标签,我们描述了整个打印页面。这个过程很简单。您只需要以点为单位设置距离即可。所有测量值均以磅为单位。
总而言之,在本文中,我们考虑了ZPL命令的一部分,以使用户了解该语言的要点。
---------------------------------------------------------------打印中文-----------------------------------------------------------
利用FntHex32.dll写了个小工具转中文到ZPL可以打印的字符
#region //API GETFONTHEX [DllImport("fnthex32.dll", CharSet = CharSet.Ansi)] public static extern int GETFONTHEX( string chnstr, string fontname, int orient, int height, int width, int bold, int italic, StringBuilder cBuf); public static string convertChineseToHex(string chStr, int width,int height) { //int MAX_BUFFER, nCount; int nCount; StringBuilder cBuf = new StringBuilder(1024); nCount = GETFONTHEX(chStr, "宋体", 0, width, height, 1, 0, cBuf); //hexbuf=~DGOUTSTR01,00120,012,gL07J018H03838H0HFEJ01IFE03H0E063EFH0C06J0H387803HFE0CF03H //0C06K06HFH03H0E1FBFEH07FHCI01C3I03HFE063BF87F078J03HFC03I01FHBD807HFJ07EH3606K0I //F8I06K0603H0CI01FDBD8I0EK07HF038J019878H07CJ0 string sEnd = "^XGOUTSTR01" + ",1,2^FS "; return (cBuf.ToString() + sEnd); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | ^FO48,68 ~DGOUTSTR01,00192,016,H038K0CL0CL0CQ0C0CI07I01806I07HFCN01JFC01IFE030IFH06H0CN03 0C1CH018H0C0E6C07H07HFCO03HF8H018H0C0FCHFCK018N0E1EI01IFC030IF87JFCO0738H018J061 EDB8038I01EL03C0FE038J0FDEDB8H0HFEN03IFEH07K01F7HF8J0CO0180EH0EK0FH6DB8I01C01EL0 1HFE018L0C60FI01F8h0 ^XGOUTSTR01,1,2^FS ^FO48,108 ~DGOUTSTR01,00192,016,0306I018018J0CL0CN01B0EI01801801806I07HFCN01B0C060DB1D8030 IFH06H0CN03JFE0DE0180E6C07H07HFCN0H3H7H61HF8180FCHFCK018M0630HE6038F98030IF87JFC N07D8CE07F81B061EDB8038I01EK03F718E0D807E0FDEDB8H0HFEO03070C1H9FD801F7HF8J0CO030 C1C0180180FH6DB8I01C01EL0378F8018018H0C60FI01F8h0 ^XGOUTSTR01,1,2^FS ^FO48,148 ~DGOUTSTR01,00192,016,H038K038J0CL06R0C0C0383B8H018I01F8EO01JFE0H639CH03HFC0761C 1CO0E1CH0CEHF6H0E038H07BHF8O0630C1HFB8603BCEH07FE38O0JFE0303FCI038H01F8F8O0CK0E3 F9CH03E0603EDHF01EL0CJ01FE1F8H0F3FE0H6H398M01CL019E31FBH060CH638CM018J03HFH73H03 H06H0EC3801EK03M07C1FH03HFEH0E0FhG0 ^XGOUTSTR01,1,2^FS ^FO48,188 ~DGOUTSTR01,00192,016,018J0180CI0706I0CH0CN019818H030DC703I6I0IFCO0JFE07HF7C037H CI0EH0CO0381801DBC180HF7HF80IFCN03F819801B7FE01FDC6078H07CN01BHF01FE60E0F67CEH0I FEQ0C1E03C7FEH0EC6CH0IFE01EK03JF807FE0E0HFC3CH0C38EO03C3CH0D87FE03D83801IFEN01EC 7E039860EH07IEH0C38C01EK030FC3E0187FE0FCF838KFCgY0 ^XGOUTSTR01,1,2^FS |
---------------------------------------------------------------用中文字体打印---------------------------------------------------
^XA ^CI26 //ASCII Transparency和多字节亚洲编码 ^SEE:GB18030.DAT //码表 ^CW1,E:SIMSUN.FNT //字体(宋体) ^FO200,200^A1N,48,48^FD中文^FS //打印文字 ^FT448,288^BQ2,2,10^A1N,48,48^FD中文^FS //打印二维码 ^XZ
C# 通过USB口连Zebra打印机,直接发ZPL命令打印
private static bool ZPLPrint(string[] args) { string s = string.Format(@"^XA ^CFB,10 ^FO10,5^FD{0}^FS ^FO10,20^FD{1}^FS ^FO10,35^FD{2}^FS ^FO10,50^FD{3}^FS ^FO10,65^FD{4}^FS ^FO10,80^FD{5}^FS ^XZ", args[0],args[1],args[2],args[3],args[4],args[5]); string printerName = System.Configuration.ConfigurationManager.AppSettings["printerName"]; var bret= RawPrinterHelper.SendStringToPrinter(printerName, s); LogInfo("****** report Finish ****"); LogInfo(""); return bret; }

1 using System; 2 using System.IO; 3 using System.Runtime.InteropServices; 4 5 namespace Zebra 6 { 7 8 9 public class RawPrinterHelper 10 { 11 // Structure and API declarions: 12 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 13 public class DOCINFOA 14 { 15 [MarshalAs(UnmanagedType.LPStr)] public string pDocName; 16 [MarshalAs(UnmanagedType.LPStr)] public string pOutputFile; 17 [MarshalAs(UnmanagedType.LPStr)] public string pDataType; 18 } 19 [DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] 20 public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd); 21 22 [DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] 23 public static extern bool ClosePrinter(IntPtr hPrinter); 24 25 [DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] 26 public static extern bool StartDocPrinter(IntPtr hPrinter, Int32 level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di); 27 28 [DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] 29 public static extern bool EndDocPrinter(IntPtr hPrinter); 30 31 [DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] 32 public static extern bool StartPagePrinter(IntPtr hPrinter); 33 34 [DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] 35 public static extern bool EndPagePrinter(IntPtr hPrinter); 36 37 [DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] 38 public static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, Int32 dwCount, out Int32 dwWritten); 39 40 // SendBytesToPrinter() 41 // When the function is given a printer name and an unmanaged array 42 // of bytes, the function sends those bytes to the print queue. 43 // Returns true on success, false on failure. 44 public static bool SendBytesToPrinter(string szPrinterName, IntPtr pBytes, Int32 dwCount) 45 { 46 Int32 dwError = 0, dwWritten = 0; 47 IntPtr hPrinter = new IntPtr(0); 48 DOCINFOA di = new DOCINFOA(); 49 bool bSuccess = false; // Assume failure unless you specifically succeed. 50 51 di.pDocName = "My C#.NET RAW Document"; 52 di.pDataType = "RAW"; 53 54 // Open the printer. 55 if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero)) 56 { 57 // Start a document. 58 if (StartDocPrinter(hPrinter, 1, di)) 59 { 60 // Start a page. 61 if (StartPagePrinter(hPrinter)) 62 { 63 // Write your bytes. 64 bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten); 65 EndPagePrinter(hPrinter); 66 } 67 EndDocPrinter(hPrinter); 68 } 69 ClosePrinter(hPrinter); 70 } 71 // If you did not succeed, GetLastError may give more information 72 // about why not. 73 if (bSuccess == false) 74 { 75 dwError = Marshal.GetLastWin32Error(); 76 } 77 return bSuccess; 78 } 79 80 public static bool SendFileToPrinter(string szPrinterName, string szFileName) 81 { 82 // Open the file. 83 FileStream fs = new FileStream(szFileName, FileMode.Open); 84 // Create a BinaryReader on the file. 85 BinaryReader br = new BinaryReader(fs); 86 // Dim an array of bytes big enough to hold the file's contents. 87 Byte[] bytes = new Byte[fs.Length]; 88 bool bSuccess = false; 89 // Your unmanaged pointer. 90 IntPtr pUnmanagedBytes = new IntPtr(0); 91 int nLength; 92 93 nLength = Convert.ToInt32(fs.Length); 94 // Read the contents of the file into the array. 95 bytes = br.ReadBytes(nLength); 96 // Allocate some unmanaged memory for those bytes. 97 pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength); 98 // Copy the managed byte array into the unmanaged array. 99 Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength); 100 // Send the unmanaged bytes to the printer. 101 bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength); 102 // Free the unmanaged memory that you allocated earlier. 103 Marshal.FreeCoTaskMem(pUnmanagedBytes); 104 return bSuccess; 105 } 106 public static bool SendStringToPrinter(string szPrinterName, string szString) 107 { 108 IntPtr pBytes; 109 Int32 dwCount; 110 // How many characters are in the string? 111 dwCount = szString.Length; 112 // Assume that the printer is expecting ANSI text, and then convert 113 // the string to ANSI text. 114 pBytes = Marshal.StringToCoTaskMemAnsi(szString); 115 // Send the converted ANSI string to the printer. 116 SendBytesToPrinter(szPrinterName, pBytes, dwCount); 117 Marshal.FreeCoTaskMem(pBytes); 118 return true; 119 } 120 } 121 122 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏
· Manus爆火,是硬核还是营销?