• BarTender 通过ZPL命令操作打印机打印条码, 操作RFID标签


    注: 

       由于工作需要, 也是第一次接触到打印机的相关内容, 凑巧, 通过找了很多资料和帮助后, 也顺利的解决了打印标签的问题

    (标签的表面信息[二维码,条形码, 文字] RFID标签的EPC写入)

    解决方案

    1. 由于开发准备的前期工作, 手里面是有很多的原厂API。

    2.熟之, 斑马打印机官方是由一套自己的打印语言, 简称ZPL语言, 然后各种费解找到官方的SBPL API, 大概就是这样/

     

    通过阅读大概阅读了这些API文档(尽管看不懂...) ,大概知道原理是通过ZPL命令发送至打印机执行。

    所以,顺藤摸瓜, 我直接就去搜索ZPL的操作命令, 自己尝试了编写ZPL命令操作打印机。在这里,先讲一下什么是ZPL命令~~

    Zebra Programming Language (printer language) 简称ZPL 是由斑马公司发明的一种用于打印机通信的命令。

    3. 在ZPL API 文档种, 会用很详细的介绍, 从是怎样开始, 到各个指令的作用都会介绍, 如下图

    根据官方的说明, 每个完整的ZPL 指令, 它都是 ^XA 开始, 以 ^Z 结束。 而^则是一个标记头, 后面跟着的字母,则是对应的作用功能, 例如:

    ^LH  : 定义标签的起始位置

    ^LL  : 定义标签的长度

    ^PW  : 打印宽度

    ^LS  : 标签的位移

    ^......

    实现

    那么现在自己组成自己想要打印的ZPL指令, 该如何发送到打印机?

    1.Demo(示例), 这里以打印一串字符 12345678 生成的ZPL指令演示如何发送到打印机

    * 12345678所生成的ZPL指令如下: 

    ^ XA ^ FO50,50 ^ A0N,36,20 ^ FD12345678 ^ FS ^ PQ1,0,1,Y ^ XZ

    注释:
    ^XA/^XZ 分别代表ZPL的开始与结束, 始终固定
    ^FO :代表字段的起始位置, 50,50代表具体的坐标位置
    ^AON,36,20: 可缩放/位图字体 O代表字体, N代表字段的方向, 36代表字符的高度,20代表宽度
    ^FD12345678^FS: 字符内容, 代表输出的字符 12345678 标准以^FS结束
    ^PQ1,0,1,Y: 打印数量, 1打印数量,0暂停和切纸值,1每个序列号的副本数,Y代表覆盖暂停计数
      

     2.核心代码( 将ZPL转换成IntPtr 然后调用 SendBytesToPrinter 方法)

    //ZPL命令测试方法
            public bool PrintZPL(string zpl)
            {
                return SendStringToPrinter("ZDesigner R110Xi4 300 dpi", zpl);
            }

    注:
    ZDesigner R110Xi4 300 dpi 是打印机的名称
    
    
            /// <summary>
            /// 内容打印
            /// </summary>
            /// <param name="szPrinterName">打印机名称</param>
            /// <param name="szString">打印的SBPL指令</param>
            /// <returns></returns>
            public bool SendStringToPrinter(string szPrinterName, string szString)
            {
                IntPtr pBytes;
                int dwCount;
                dwCount = szString.Length;
                pBytes = Marshal.StringToCoTaskMemAnsi(szString);
                SendBytesToPrinter(szPrinterName, pBytes, dwCount);
                Marshal.FreeCoTaskMem(pBytes);
                return true;
            }
            // Structure and API declarions:
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
            public class DOCINFOA
            {
                [MarshalAs(UnmanagedType.LPStr)]
                public string pDocName;
                [MarshalAs(UnmanagedType.LPStr)]
                public string pOutputFile;
                [MarshalAs(UnmanagedType.LPStr)]
                public string pDataType;
            }
            [DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
            public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, int pd);
    
            [DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
            public static extern bool ClosePrinter(IntPtr hPrinter);
    
            [DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
            public static extern bool StartDocPrinter(IntPtr hPrinter, Int32 level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);
    
            [DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
            public static extern bool EndDocPrinter(IntPtr hPrinter);
    
            [DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
            public static extern bool StartPagePrinter(IntPtr hPrinter);
    
            [DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
            public static extern bool EndPagePrinter(IntPtr hPrinter);
    
            [DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
            public static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, Int32 dwCount, out Int32 dwWritten);
    
            public static bool SendBytesToPrinter(string szPrinterName, IntPtr pBytes, Int32 dwCount)
            {
                Int32 dwError = 0, dwWritten = 0;
                IntPtr hPrinter = new IntPtr(0);
                DOCINFOA di = new DOCINFOA();
                bool bSuccess = false; // Assume failure unless you specifically succeed.
    
                di.pDocName = "labelprint";
                di.pDataType = "RAW";
    
                // Open the printer.
                if (OpenPrinter(szPrinterName, out hPrinter, 0))
                {
                    // Start a document.
                    if (StartDocPrinter(hPrinter, 1, di))
                    {
                        // Start a page.
                        if (StartPagePrinter(hPrinter))
                        {
                            // Write your bytes.
                            bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
                            EndPagePrinter(hPrinter);
                        }
                        EndDocPrinter(hPrinter);
                    }
                    ClosePrinter(hPrinter);
                }
                // If you did not succeed, GetLastError may give more information
                // about why not.
                if (bSuccess == false)
                {
                    dwError = Marshal.GetLastWin32Error();
                }
                return bSuccess;
            }

    3.最终效果

     

    ### 华 丽 的 分 割 线  ###

    原理

    *: 看官方的API没有实际的例子不好学习和了解怎么办? 同时, 官方提供的标签设计软件(bartender)是可以将数据预先设置好,

    导出本地文件的,这样更加方便学习。

    1.打开已经破解版本的Bartender9.4演示如何将设计的标签导出本地文件,然后查看ZPL指令.

     >1.打开Bartender9.4

    >2..选择一个新的标签格式即可, 一直下一步, 直到进入主界面, 给标签添加一个文本数据: 12345678 为例

     

    >3.然后选择打印按钮

    >4.勾选打印至文件, 保存至本地文件。

    >5.打开刚才保存的文件, 找到里面的内容

    里面的内容, 由两个 ^XA ~ ^XZ 组成, 还有一些XML标签组成。  很明显, 第二个 ^XA-^XZ 是我们打印的实际内容指令; 

     >6. 像图中的 <xpml>标签 <page>标签, 这些应该是软件里面的数据格式, 肯定没用处的, 所以我们找到需要的内容即可, 然后放在测试程序里面。

     

     

     : 调用代码

            /// <summary>
            /// 测试ZPL命令执行
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btn_print_Click(object sender, EventArgs e)
            {
                if (string.IsNullOrEmpty(txt_zpl.Text)) return;
    
                SendStringToPrinte("ZDesigner R110Xi4 300 dpi",txt_zpl.Text); 
            }
            public static bool SendStringToPrinter(string szPrinterName, string szString)
            {
                IntPtr pBytes;
                Int32 dwCount;
                dwCount = szString.Length;
                pBytes = Marshal.StringToCoTaskMemAnsi(szString);
                SendBytesToPrinter(szPrinterName, pBytes, dwCount);
                Marshal.FreeCoTaskMem(pBytes);
                return true;
            }

    注: 由于标签纸的大小问题, 在设置标签模板的时候, 我是选定了标签的长宽, 如果出现打印不出来

    或者显示不全的, 可以在标签模板设置好长宽和条码的位置即可

    PS:本章未更新关于RFID打印的相关内容, 需要了解, 请联系本人邮件。 

    需要源代码请发送至本人邮箱, zhouhaogg789@outlook.com, 看到会及时回复!

    #

    模板打印

    代码贴了这么多, 可能还不知道引用了什么DLL, 指令也是刚刚接触,可能只有博主自己懂, 那还有没有更好更简单的方法实现呢?

    解决方案:  《模板打印》

    1.设置好打印的标签模板

       工具: Bartender9.4

    2.用代码给调用模板赋值

    3.调用打印

    #

    1. Bartender 官方提供的标签设计软件, 同时具体所有的打印功能。

    Bartender标签软件内部原理也无非一样: 1.设计好标签数据。2.打印的时候生成指令的语言发送至打印机打印。

    同时Bartender也可以将设计好的样式导出模板,用于外部赋值参数打印。

    友情连接: http://www.cnblogs.com/zh7791/p/6907455.html

  • 相关阅读:
    Qt之课外实践——文件操作(简单清道夫)
    【转载】2018 hosts 持续更新访问 gu歌【更新于:2018-05-03】
    NBU基本常用命令
    运维的四个发展阶段,看看自己在哪个阶段,聊聊怎么升级打怪
    云笔记使用心得分享
    LNMP一键安装包
    expect脚本中,变量的写法
    VERITAS NETBACKUP运维手册(工作总结)
    善用良器:帮你有效管理时间的7种工具
    RAID0 1 5 10原理、种类及性能优缺点对比
  • 原文地址:https://www.cnblogs.com/zh7791/p/6905130.html
Copyright © 2020-2023  润新知