ZPL(Zebra Programming Language) 是斑马公司(做条码打印机的公司)自己设计的语言, 由于斑马打印机是如此普遍, 以至于据我所见所知, 条码打印机全部都是斑马的, 所以控制条码打印机几乎就变成了对ZPL的使用.

总的逻辑分为以下两步:

(1)编写ZPL指令

(2)把ZPL作为C#的字符串, 由C#把它送至连接打印机的端口.

其中, 用C#把字符串送并口的写法是固定的, 这部分的代码如下:

public class Printer
{[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]private struct OVERLAPPED { int Internal; int InternalHigh; int Offset; int OffSetHigh; int hEvent; } [System.Runtime.InteropServices.DllImport("kernel32.dll")] private static extern int CreateFile( string lpFileName, uint dwDesiredAccess, int dwShareMode, int lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, int hTemplateFile ); [System.Runtime.InteropServices.DllImport("kernel32.dll")] private static extern bool WriteFile( int hFile, byte[] lpBuffer, int nNumberOfBytesToWrite, out int lpNumberOfBytesWritten, out OVERLAPPED lpOverlapped ); [System.Runtime.InteropServices.DllImport("kernel32.dll")] private static extern bool CloseHandle( int hObject ); private int iHandle; public bool Open() { iHandle = CreateFile("LPT1:", (uint)FileAccess.ReadWrite, 0, 0, (int)FileMode.Open, 0, 0); if (iHandle != -1) { return true; } else { return false; } } public bool Write(string Mystring) { if (iHandle != -1) { int i; OVERLAPPED x; byte[] mybyte = System.Text.Encoding.Default.GetBytes(Mystring); return WriteFile(iHandle, mybyte, mybyte.Length, out i, out x); } else { throw new Exception("端口未打开!"); } } public bool Close() { return CloseHandle(iHandle); } }

这个类封装了对并口的操作, 它的使用方法为:

var printer = new Printer();
if (!printer.Open())
{GB.IO.SetError("未能连接打印机,请确认打印机是否安装正确并接通电源。");return;
}
printer.Write(cmd);
if (!printer.Close()) { GB.IO.SetError("未能关闭与打印机之间的连接,这可能意味着严重的错误,请重启电脑及打印机。"); return; } 
其中, cmd即是构造好的ZPL指令. 
现在来看一段示意ZPL指令. 

^XA ^MD30 ^LH60,10 ^FO20,10 ^ACN,18,10 ^BY1.4,3,50 ^BC,,Y,N ^FD01008D004Q-0^FS ^XZ

这是一段能够实际执行的指令串, 下面逐行解释. 
第一句^XA和最后一句^XZ分别代表一个指令块的开始和结束, 是固定的东西. 
^MD是设置色带颜色的深度, 取值范围从-30到30, 上面的示意指令将颜色调到了最深. 
^LH是设置条码纸的边距的, 这个东西在实际操作上来回试几次即可.
^FO是设置条码左上角的位置的, 这个对程序员应该很容易理解. 0,0 代表完全不留边距. 
^ACN是设置字体的. 因为在条码下方会显示该条码的内容, 所以这里要设一下字体. 这个字体跟条码无关.
^BY是设置条码样式的, 这是最重要的一个东西, 1.4是条码的缩放级别, 这个数值下打出的条码很小, 3是条码中粗细柱的比例, 50是条码高度.
^BC是打印code128的指令, 具体参数详见ZPL的说明书. 
^FD设置要打印的内容, ^FS表示换行. 
所以上述语句最终的效果就是打印出一个值为01008D004Q-0的条码, 高度为50. 
以上可以看出, ZPL的指令方式很简单, 实际上, 如果打印要求不复杂的话, 基本上也就用得上上述的几个指令了, 
其它的指令虽然很多, 但是基本上可以无视. 
其实即使要打图形之类的东西, 也并不复杂, 例如GB可以打印出来一个边框, GC打印一个圆圈等. 其它的自定义图案需要先把图案上传至打印机, 
指令部分只要选择已上传的图案, 选择方式跟上面的字体选择类似, 也很简单. 
 
在实践中, 常常会需要一次横打两张, 其实可以把一排的两张想像成一张, 连续执行两个打印命令, 把第二个FO的横坐标设置得大一些就行了.  例如: ^XA  ^FO20,10 ^FD001^FS  ^FO60,10 ^FD002^FS  ^XZ 第一对FO/FD命令打印左侧, 第二对FO/FD命令打印右侧. 
具体的指令详细解释, 及要实现其它功能, 可下载 ZPL II Programming Guide, 这本书写得非常详细. (如链接不能下载, google书名即可)----------2013/9/18 更新 将指令发送到打印机的代码, 上述做法仅限于打印机在本地,且接在并口1上面,如果打印机在远程, 或者打印机不是并口的, 可以通过驱动程序来发送指令。 这要求首先在操作系统中装好打印机驱动,调试无误以后, 记录下驱动中打印机的名称, 然后向此打印机发送指令, 与打印机驱动通信的类如下: 
?
public class RemotePrinter
     {
         // 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, IntPtr 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);
         // 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)
         {
             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 = "My C#.NET RAW Document" ;
             di.pDataType = "RAW" ;
             // Open the printer.
             if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
             {
                 // 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;
         }
         public static bool SendFileToPrinter( string szPrinterName, string szFileName)
         {
             // Open the file.
             FileStream fs = new FileStream(szFileName, FileMode.Open);
             // Create a BinaryReader on the file.
             BinaryReader br = new BinaryReader(fs);
             // Dim an array of bytes big enough to hold the file's contents.
             Byte[] bytes = new Byte[fs.Length];
             bool bSuccess = false ;
             // 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;
         }
         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 ;
         }
     }

  

 在调用时, 只要调用RemotePrinter.SendStringToPrinter方法即可, 第一个参数是打印机的名称(驱动中显示的名称), 第二个参数是命令。
 

---------------------------------------------

作者:夏狼哉 博客:http://www.cnblogs.com/Moosdau

如需引用,敬请保留作者信息,谢谢

转载于:https://www.cnblogs.com/goodsmith/p/4797685.html

C#打印条码与ZPL相关推荐

  1. 在网络上共享条码打印机

    原来写过一篇C#打印条码与ZPL, 是打印到本地的打印机, 但是往往会需要程序使用远程的打印机进行打印,  其实基本上做法是一致的, 只是把命令发送到打印机的地方修改一下. 具体发送指令的代码微软已经 ...

  2. ZPL 打印条码、二维码及小票(中文/汉字),生成条码、二维码图片【Asp.Net】-含示例代码

    生成条码(图1).二维码(图2)图片及打印出二维码标签(图3)效果                 图1                                       图2        ...

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

    解决方案 1. 由于开发准备的前期工作, 手里面是有很多的原厂API, 通过阅读大概阅读了这些pdf文档(尽管看不懂...) ,大概知道原理是通过ZPL命令去调用DLL发送至打印机执行. 所以,顺藤摸 ...

  4. C#发送ZPL控制斑马Zebra打印机源码

    1.最近想把斑马打印机集成到自己的C#程序里,找了好多资料,最后采用通过发送ZPL语言给打印机来完成打印这种方式,该程序可以创建.保存.调用ZPL模板,可以修改打印条码的参数并保存到模板里. 2.下面 ...

  5. [C#] ZEBRA ZPL指令打印BarCode,QRCode

    公司业务需要 接触到c#的打印机方面的业务.要求客户端控制打印机来打印条码,二维码. 条码:在条码打印上 在传参方面和排版方面需要去慢慢调试. 二维码:直接指令打印二维码在控制二维码大小很难把控,因为 ...

  6. java如何判断打印是否成功_如何验证Zebra打印机是否使用ZPL和C#成功打印(或能够检测到错误)?...

    问题 是否有一个简单的ZPL代码或方法从Zebra打印机返回错误消息,以确定标签是否未成功打印或是否存在某种错误? 进展 这是我为将打印机作业发送到zebra打印机而构建的一个很好的功能: publi ...

  7. php 怎么打印条形码,php – 如何在垂直标签中垂直打印zpl条形码

    我正在使用zebraGk420d打印机.我正在使用垂直条形码标签.如何垂直打印文本和条形码.我的zpl代码是这样的 $barcode_ZPL_code="^XA ^FO 150,50^AD, ...

  8. C#-利用ZPL语言完毕条形码的生成和打印

     近期由于公司项目的须要,研究了一项对我来说算是新的技术-条形码的生成和打印.由于之前没有接触过这方面的知识,所以刚開始还有点小迷茫和小兴奋,只是一步一步来,问题总会解决的.如今来总结一下做条形码 ...

  9. c#endread怎么打印出来_C#编程直接发送打印机命令到打印机及ZPL常用的打印命令详解...

    本文主要向大家介绍了C#编程直接发送打印机命令到打印机及ZPL常用的打印命令详解,通过具体的内容向大家展示,希望对大家学习C#编程有所帮助. using System; using System.Co ...

最新文章

  1. 深入了解以太坊虚拟机第3部分——动态数据类型的表示方法
  2. javascript系列--javascript数组的常用算法解析
  3. python方法items_Python字典items()方法与示例
  4. 动态网页开发技术(一):Servlet
  5. 机房计算机组网方案,网络机房测试方案
  6. 恩淑 2004-12-18
  7. 在数据库中存储IP地址
  8. 离开后再回原来的公司合适吗?
  9. 你真的知道什么是置信区间吗?
  10. python 导入sklearn时报错: no model named ‘murmurhash‘
  11. 我愿称之为最强归纳—浮点数的规格化与进制数之间的转换
  12. 3D游戏建模师看不看学历?现在转行还能行吗?
  13. java通过ftl模板导出word最详细教程
  14. 实验8 缓冲区溢出攻击实验
  15. 怎么搭建一份好的产品宣传手册?方法来了
  16. 依赖Api的exclude行为失效
  17. 【问题解决】Error:(3, 46) java: 程序包org.springframework.context.annotation不存在
  18. java基于Android校园购物商城小超市
  19. 以我的区长父亲为题目写一篇作文
  20. Linux环境下制作启动U盘

热门文章

  1. 【BZOJ3309】DZY Loves Math(线性筛)
  2. python给视频加背景音乐_python给视频添加背景音乐并改变音量的具体方法
  3. PICT的介绍与使用
  4. android手机远程控制_如何远程查看和控制您的Android手机
  5. Python关键字(保留字)
  6. java实现微信消息和小程序模板消息推送
  7. 第18.8.3章 JDK9-16变化—GC方面新特性
  8. 日本語:日常会话7-スイーツ【すいーつ】店
  9. python制作表情_python实现表单中插入表情符号
  10. Node.js + Vue.js 全栈开发王者荣耀手机端官网和管理后台