C#打印条码与ZPL
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相关推荐
- 在网络上共享条码打印机
原来写过一篇C#打印条码与ZPL, 是打印到本地的打印机, 但是往往会需要程序使用远程的打印机进行打印, 其实基本上做法是一致的, 只是把命令发送到打印机的地方修改一下. 具体发送指令的代码微软已经 ...
- ZPL 打印条码、二维码及小票(中文/汉字),生成条码、二维码图片【Asp.Net】-含示例代码
生成条码(图1).二维码(图2)图片及打印出二维码标签(图3)效果 图1 图2 ...
- BarTender 通过ZPL命令操作打印机打印条码, 操作RFID标签
解决方案 1. 由于开发准备的前期工作, 手里面是有很多的原厂API, 通过阅读大概阅读了这些pdf文档(尽管看不懂...) ,大概知道原理是通过ZPL命令去调用DLL发送至打印机执行. 所以,顺藤摸 ...
- C#发送ZPL控制斑马Zebra打印机源码
1.最近想把斑马打印机集成到自己的C#程序里,找了好多资料,最后采用通过发送ZPL语言给打印机来完成打印这种方式,该程序可以创建.保存.调用ZPL模板,可以修改打印条码的参数并保存到模板里. 2.下面 ...
- [C#] ZEBRA ZPL指令打印BarCode,QRCode
公司业务需要 接触到c#的打印机方面的业务.要求客户端控制打印机来打印条码,二维码. 条码:在条码打印上 在传参方面和排版方面需要去慢慢调试. 二维码:直接指令打印二维码在控制二维码大小很难把控,因为 ...
- java如何判断打印是否成功_如何验证Zebra打印机是否使用ZPL和C#成功打印(或能够检测到错误)?...
问题 是否有一个简单的ZPL代码或方法从Zebra打印机返回错误消息,以确定标签是否未成功打印或是否存在某种错误? 进展 这是我为将打印机作业发送到zebra打印机而构建的一个很好的功能: publi ...
- php 怎么打印条形码,php – 如何在垂直标签中垂直打印zpl条形码
我正在使用zebraGk420d打印机.我正在使用垂直条形码标签.如何垂直打印文本和条形码.我的zpl代码是这样的 $barcode_ZPL_code="^XA ^FO 150,50^AD, ...
- C#-利用ZPL语言完毕条形码的生成和打印
近期由于公司项目的须要,研究了一项对我来说算是新的技术-条形码的生成和打印.由于之前没有接触过这方面的知识,所以刚開始还有点小迷茫和小兴奋,只是一步一步来,问题总会解决的.如今来总结一下做条形码 ...
- c#endread怎么打印出来_C#编程直接发送打印机命令到打印机及ZPL常用的打印命令详解...
本文主要向大家介绍了C#编程直接发送打印机命令到打印机及ZPL常用的打印命令详解,通过具体的内容向大家展示,希望对大家学习C#编程有所帮助. using System; using System.Co ...
最新文章
- 深入了解以太坊虚拟机第3部分——动态数据类型的表示方法
- javascript系列--javascript数组的常用算法解析
- python方法items_Python字典items()方法与示例
- 动态网页开发技术(一):Servlet
- 机房计算机组网方案,网络机房测试方案
- 恩淑 2004-12-18
- 在数据库中存储IP地址
- 离开后再回原来的公司合适吗?
- 你真的知道什么是置信区间吗?
- python 导入sklearn时报错: no model named ‘murmurhash‘
- 我愿称之为最强归纳—浮点数的规格化与进制数之间的转换
- 3D游戏建模师看不看学历?现在转行还能行吗?
- java通过ftl模板导出word最详细教程
- 实验8 缓冲区溢出攻击实验
- 怎么搭建一份好的产品宣传手册?方法来了
- 依赖Api的exclude行为失效
- 【问题解决】Error:(3, 46) java: 程序包org.springframework.context.annotation不存在
- java基于Android校园购物商城小超市
- 以我的区长父亲为题目写一篇作文
- Linux环境下制作启动U盘
热门文章
- 【BZOJ3309】DZY Loves Math(线性筛)
- python给视频加背景音乐_python给视频添加背景音乐并改变音量的具体方法
- PICT的介绍与使用
- android手机远程控制_如何远程查看和控制您的Android手机
- Python关键字(保留字)
- java实现微信消息和小程序模板消息推送
- 第18.8.3章 JDK9-16变化—GC方面新特性
- 日本語:日常会话7-スイーツ【すいーつ】店
- python制作表情_python实现表单中插入表情符号
- Node.js + Vue.js 全栈开发王者荣耀手机端官网和管理后台