^FO10,10^BY2,11.0,10,40^BCC,90,N^FD12345678^FS ^FX 二维码 ^FO10,10^BQ,2,5^CI26^FH^FDQA^FD1215445244^FS
^FO10,10^AFN,0,20,10^FD123456^FS

打印一维码

^FO10,10^BY2,11.0,10,40^BCC,80,N^FD12345678^FS

其中^BCC,80,N的80为一维码的高度,N表示不显示注释行,则显示内容12345678

打印二维码

^FO10,10^BQ,2,5^CI26^FH^FDQA^FD1215445244^FS

其中^BQ,2,5的5为二维码大小,范围1-10

关于中文打印

由于打印机没有中文的字库,打印中文会 出现乱码

一种解决方法就是安装中文字符,码表,这个有点麻烦,就不用了

另一种就是, 通过Fnthex32.dll,将文字转为打印机指令,再发送到打印机

Fnthex32.dll下载:

链接: https://pan.baidu.com/s/1_lU0zswvE929wpXG0431Wg
提取码:oi41

[DllImport("Fnthex32.dll")]
private static extern int GETFONTHEX(
string text,//文本
string fontName,//字体
string tempName,//临时变量
int orient,//方向
int height,//字体高度
int width,//字体宽度
int isBold,//是否加粗0,1
int isItalic,//是否斜体0,1
StringBuilder cmd);//内容
/// <summary>
/// 获取文本编码
/// </summary>
/// <param name="text">文本</param>
/// <param name="fontName">字体</param>
/// <param name="tempName">临时变量</param>
/// <param name="height">字体高度</param>
/// <param name="width">字体宽度</param>
/// <param name="isBlod">是否加粗</param>
/// <param name="isItalic">是否斜体</param>
/// <returns></returns>
public static string GetFontHex(string text, string fontName, string tempName,
    int height = 40, int width = 15, bool isBlod = false, bool isItalic = false)
    int nIsBlod = isBlod ? 1 : 0;
    int nIsItalic = isItalic ? 1 : 0;
    StringBuilder context = new StringBuilder(text.Length * 1024);
    int count = GETFONTHEX(text, fontName, tempName, 1, height, width, nIsBlod, nIsItalic, context);
    string temp = " " + context.ToString();
    temp = temp.Substring(0, count);
    return temp;

通过GetFontHex获取ZPL指令

 string sTemp = GetFontHex("啊", "Arial", "temp0");

其中temp0是一个临时变量

接下来,再通过一条指令来设置

^FO30,0^XGtemp0,1,1^FS
^LH0,0^LL80^PW580 ~DGtemp0,00240,006,iH0108H0CL01FDHFEJ03F918018J031918018J03191H018J03191H018J031 93H018J03192H198J031921F98J03192H198J03194H198J03192H198J0319I198J0319I198J03191 9198J031909198J03190D198J03190DF98J03F90D198J031919H18J03H1F8018J03013H018L01I01 8L01I018L01I018L01I018L01I018L01H01F8L01I07M01I02iK0 ^FO30,0^XGtemp0,1,1^FS

关于图片的打印

打印图片,需要将图片转换成十六进制指令

https://blog.csdn.net/weixin_38211198/article/details/96494614

指令发送到打印机

首选需要设置打印机共享

才使用System.IO.File.Copy方法

//保存到本地文件
using (System.IO.StreamWriter sw = new System.IO.StreamWriter(printFilePath))
    sw.Write(cmd.ToString());
//将ZPL指令发送到打印机
File.Copy(printFilePath, mPrintName, true);
 

printFilePath为ZPL指令文件路径

mPrintName为打印机路径,例如:mPrintName = @"\\192.168.0.132\TSC TE344";

指令需要获取本机IP4地址

/// <summary>
/// 获取IP4地址
/// </summary>
private string GetIP4()
    string ip4 = string.Empty;
    IPHostEntry ipe = Dns.GetHostEntry(Dns.GetHostName());
    IPAddress[] ips = ipe.AddressList;
    for (int i = 0; i < ips.Length; i++)
        if (ips[i].AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
            ip4 = ips[i].ToString();
            break;
    return ip4;
 

其实本机IP直接写127.0.0.1就好

关于打印机初始化

由于之前使用佳博Gprinter GP-9134T打印机,不是使用ZPL指令,直接使用PrintDocument类打印控件的图片,打印机都是自动校准的,现在TSC TE344打印机,由于现在打印机没有校准功能,用PrintDocument打印总是会打印一半纸张,所以改为ZPL指令打印,为了能同时使用多种打印机,之后做兼容。

由于用PrintDocument打印,导致出纸不准确,可用下面这指令初始化打印机,这指令是从NiceLabel得到的

首先,要设置好打印纸张的大小,边距等,在打印到文件,即可获取该初始化指令(BarTender)

/// <summary>
/// 打印机初始化
/// </summary>
private void PrintInit()
    string printerInitCMD = @"
                              <xpml><page quantity='0' pitch='15.1 mm'></xpml>SIZE 47.5 mm, 15.1 mm
                              GAP 2 mm, 0 mm
                              DIRECTION 0,0
                              REFERENCE 0,0
                              OFFSET 0 mm
                              SET PEEL OFF
                              SET CUTTER OFF
                              SET PARTIAL_CUTTER OFF
                              <xpml></page></xpml><xpml><page quantity='1' pitch='15.1 mm'></xpml>SET TEAR ON
                              <xpml></page></xpml><xpml><end/></xpml>";
    string PrinterInitFilePath = printPath + "\\PrinterInit.prn";
    using (StreamWriter sw = new StreamWriter(PrinterInitFilePath))
        sw.Write(printerInitCMD);
   File.Copy(PrinterInitFilePath, mPrintName, true);

使用的打印纸规格

双排打印纸

实际大小(mm)

标签宽高:22*15

卷宽:50

 左右边距:2  

代码中大小

标签宽高:235*160

纸张宽度:580

左右边距:30

中缝边距:50

由于ZPL刚学,不熟悉,项目中需要支持自定义打印模板功能,即用户自己调整,拖拽标签位置等,

1.ZPL预览功能有点难度

2.ZPL指令的参数限制,比如条码的宽高无法与控件的大小兼容

所以直接通过打印控件上的图片,将图片转为十六进制指令发送到打印机,

这样还有一个好处就是不用考虑中文乱码的问题

下面是我的PrintManager

public class PrintManager
    #region 文字转图像
    [DllImport("Fnthex32.dll")]
    private static extern int GETFONTHEX(
    string text,//文本
    string fontName,//字体
    string tempName,//临时变量
    int orient,//方向
    int height,//字体高度
    int width,//字体宽度
    int isBold,//是否加粗0,1
    int isItalic,//是否斜体0,1
    StringBuilder cmd);//内容
    /// <summary>
    /// 获取文本编码
    /// </summary>
    /// <param name="text">文本</param>
    /// <param name="fontName">字体</param>
    /// <param name="tempName">临时变量</param>
    /// <param name="height">字体高度</param>
    /// <param name="width">字体宽度</param>
    /// <param name="isBlod">是否加粗</param>
    /// <param name="isItalic">是否斜体</param>
    /// <returns></returns>
    public static string GetFontHex(string text, string fontName, string tempName,
        int height = 40, int width = 15, bool isBlod = false, bool isItalic = false)
        int nIsBlod = isBlod ? 1 : 0;
        int nIsItalic = isItalic ? 1 : 0;
        StringBuilder context = new StringBuilder(text.Length * 1024);
        int count = GETFONTHEX(text, fontName, tempName, 1, height, width, nIsBlod, nIsItalic, context);
        string temp = " " + context.ToString();
        temp = temp.Substring(0, count);
        return temp;
    #endregion
    //纸张宽度
    int paperWidth = 580;
    //左右边距
    int padding = 30;
    //中缝边距
    int middlePadding = 50;
    //标签宽度
    int labelWidth = 235;
    //标签高度
    int labelHeight = 160;
    string ip4;
    public  StringBuilder cmd;
    //打印目录
    string printPath;
    //保存打印指令
    string printFilePath ;
    //打印机名称
    private string mPrintName;
    public PrintManager()
         printPath = Application.StartupPath + "\\Print";
        if (Directory.Exists(printPath) == false)
            Directory.CreateDirectory(printPath);
         printFilePath = printPath + "\\print.prn";
        ip4 = GetIP4();
    public void Init(string printerName)
        mPrintName = string.Format(@"\\{0}\{1}", ip4, printerName);
        //mPrintName = @"\\192.168.0.132\TSC TE344";
        //打印机初始化
        PrintInit();
        cmd = new StringBuilder();
        cmd.AppendFormat(@"^XA^LH0,0^LL{0}^PW{1}", 80, paperWidth);
    /// <summary>
    /// 获取IP4地址
    /// </summary>
    private string GetIP4()
        string ip4 = string.Empty;
        IPHostEntry ipe = Dns.GetHostEntry(Dns.GetHostName());
        IPAddress[] ips = ipe.AddressList;
        for (int i = 0; i < ips.Length; i++)
            if (ips[i].AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                ip4 = ips[i].ToString();
                break;
        return ip4;
    /// <summary>
    /// 打印机初始化
    /// </summary>
    private void PrintInit()
        string printerInitCMD = @"
                                  <xpml><page quantity='0' pitch='15.1 mm'></xpml>SIZE 47.5 mm, 15.1 mm
                                  GAP 2 mm, 0 mm
                                  DIRECTION 0,0
                                  REFERENCE 0,0
                                  OFFSET 0 mm
                                  SET PEEL OFF
                                  SET CUTTER OFF
                                  SET PARTIAL_CUTTER OFF
                                  <xpml></page></xpml><xpml><page quantity='1' pitch='15.1 mm'></xpml>SET TEAR ON
                                  <xpml></page></xpml><xpml><end/></xpml>";
        string PrinterInitFilePath = printPath + "\\PrinterInit.prn";
        using (StreamWriter sw = new StreamWriter(PrinterInitFilePath))
            sw.Write(printerInitCMD);
       File.Copy(PrinterInitFilePath, mPrintName, true);
    /// <summary>
    /// 打印
    /// </summary>
    public void Print()
        cmd.Append("^XZ");
        //保存到本地文件
        using (System.IO.StreamWriter sw = new System.IO.StreamWriter(printFilePath))
            sw.Write(cmd.ToString());
        //将ZPL指令发送到打印机
        File.Copy(printFilePath, mPrintName, true);
    /// <summary>
    /// 设置文本-中文乱码
    /// </summary>
    public void SetText(string value, Point loc)
        cmd.AppendFormat("^FO{0},{1}^AFN,0,20,10^FD{2}^FS", padding + loc.X, loc.Y, value);
    int iTemp = 0;
    /// <summary>
    /// 设置文本-中文正常
    /// </summary>
    public void SetText_Chinese(string value, Point loc)
        string tempName = "temp" + iTemp;
        string sTemp = GetFontHex(value, "Arial", tempName);
        cmd.Append(sTemp);
        cmd.AppendFormat("^FO{0},{1}^XG{2},1,1^FS", padding + loc.X, loc.Y, tempName);
        iTemp++;
    /// <summary>
    /// 设置二维码
    /// </summary>
    public void SetQR_Code(string value, Point loc, int size)//0到10
        cmd.AppendFormat("^FO{0},{1}^BQ,2,{2}^CI26^FH^FDQA^FD{3}^FS", padding + loc.X, loc.Y, size, value);
    /// <summary>
    /// 设置一维码
    /// </summary>
    public void SetCODE_128(string value, Point loc, Size size)
        cmd.AppendFormat(@"^FO{0},{1}^BY2,11.0,60,{2}^BCC,{3},N^FD{4}^FS", padding + loc.X, loc.Y, size.Width, size.Height, value);
    int iTemp2 = 0;
    /// <summary>
    /// 设置图片
    /// </summary>
    public void SetImage(Image image, bool isRight = false)
        image = ReSizeImage(image, new Size(labelWidth + 20, labelHeight));
        string data = ZebraUnity.BitmapToHex(image, out int to, out int row);
        string zpl = string.Format("~DGR:Temp{0}.GRF,{1},{2},{3}", iTemp2, to, row, data);
        cmd.Append(zpl);
        int offset = isRight == true ? labelWidth + middlePadding : 0;
        cmd.AppendFormat("^FO{0},0^XGR:Temp{1}.GRF,1,1^FS", padding + offset, iTemp2);
        iTemp2++;
    /// <summary>
    /// 改变图像大小
    /// </summary>
    public static Image ReSizeImage(Image img, Size size)
        Bitmap bitmap = new Bitmap(size.Width, size.Height);
        Graphics g = Graphics.FromImage(bitmap);
        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
        g.DrawImage(img, 0, 0, bitmap.Width, bitmap.Height);
        g.Dispose();
        return bitmap;
 

其中ZebraUnity.BitmapToHex 看 https://blog.csdn.net/weixin_38211198/article/details/96494614

相关链接:

ZPL指令解析:

百度文库:https://wenku.baidu.com/view/ec78b8cbf01dc281e43af039.html

道客巴巴:http://www.doc88.com/p-2018927808824.html

ZPL指令预览:

http://labelary.com/viewer.html

ZPL一些简单的指令^XA 开始^XZ 结束^LL 设置标签长度(我用的打印机是TSC TE344,这好像没有效果)^PW 设置标签宽度^FS 换行^FS 注释^LH0,0 纸张的边距,左边距和上边距^FO0,0设置打印内容坐标^FD123 设置打印内容,可以是文本,一维码,二维码更多指令:请看这里一段完整的ZPL指令... using System.Drawing; using System.Drawing.Drawing2D; using System.Runtime.InteropServices; namespace Zebra /// <summary> ^CW1,E:SIMSUN.FNT  //字体(宋体) ^FO200,200^A1N,48,48^FD中文^FS //打印文字 ^FT448,288^BQ2,2,10^A1N,48,48^FD中文^FS  //打印二维码
该篇介绍了Zebra打印机打印中文+英文+图片的方法,如果是单单打印英文的话,可使用Zebra自带指令打印Zebra利用指令绘制出图像打印。还有一篇博客是介绍Zebra三种打印方式的利弊Zebra斑马打印机三种打印方式的利弊 打印机专栏:打印机程序开发(Zebra、TSC、Toshiba) 源码地址:https://download.csdn.net/download/horseroll/10...
由于公司一个地方需要用到图片转换ZPL格式打印;这里的ZPL格式打印斑马打印机,这里面有一些小的地方是需要注意的. 由于斑马打印机的型号不一样,设置不一样,外加自身的图片格式(.jpg,.png的不一样),图片的高度和宽度也不一样,就会直接导致打印出来的东西和你理想中的效果不一样,所以这里就需要设置图片的参数和斑马打印机自身的参数等设置。 然后下面贴出来图片转换为ZPL格式的代码,也可以当...
亮点三:可根据zpl指令预览标签样式(该样式就是打印后的样式) 亮点四:.............. ------------------------------------------------------ 价格不贵,程序不烂,简单而不简陋,绝对物有所值!!! 条码打印精致版请转到 :https://download.csdn.net/download/weixin_42270683/48947209
^A 缩放/点阵字体   ^A(可缩放/点阵字体)命令用于内置的True Type字体。可缩放字体(也可以认为是平滑矢量字体)能够以点为单位来对横向、纵向进行扩展。点阵字体由点阵象素组成,通常高度高度大于宽度。   内置的的缩放字体(A0=CG Triumvirate Bold Condensed)默认为不旋转,15点高,12点宽。打印机将从^A命令得到字体的旋转方向、宽度、高度等参数。 ^A命令的格式:   ^Af,o,h,w
zd888是一种打印机型号,常用的打印语言为ZPL(Zebra Programming Language),基于ASCII字符集编写,用于控制标签打印机打印标签和标签样式。然而,ZPL无法直接打印中文。这是因为中文字符不在ASCII字符集中,需要使用Unicode编码进行转换。在ZPL中可以通过打印间接的中文字符转换为相应的Unicode编码来实现中文打印。此外,在进行ZPL中文打印时,需要确保打印机设置正确的中文字符集,比如GB2312或UTF-8,以保证中文打印的正确性。如果需要更加便捷地打印中文,则可以考虑使用其他打印语言或打印软件,比如ESC/POS或使用第三方驱动程序,以实现中文打印的需求。