汉字、图形,Zebra打印机完全解决方案
最近在做一个项目,使用Zebra Z4M Plus打印机打印访客人员卡片。以前用过不少打印机,普通的就不说了,证件类的如DataCard等。打印方式使用的是标准的Windows打印。可以很容易的集成进我们开发的绘图程序。这次第一次使用Zebra的打印机,熟悉了1天后,发现用标准的Windows打印简直是不可能。即使是使用了Zebra的ZebraDesigner软件,制作了标签,也打不出中文来(不知是不是设置的问题)。后来换了Codesoft,在字体设置里选择Graphic方式,才打印出来。但是我要集成进自己的程序里啊,不知道该怎么做。之后是极度郁闷的2天,先是狂学习ZPL,然后是在网上找有没有类似的例子。
这里说一下,Zebra的中文支持很差的,卖东西的人技术支持都不行。Zebra中国公司又不亲自做技术支持,技术文档全是英文的,感觉四处无门,很是郁闷。在网上找了找,还是有些收获。首先找到了上海朗风,他们论坛里的一些帖子解决了我的部分问题,另外,在他们网站上找到了比较好用的海鸥驱动和一个简短的中文手册。其次,找到了一个用Delphi写的名叫Barcode的程序,调用了Fnthex32.dll中封装的斑马机打印中东地区字符的函数GETFONTHEX。最后,找到一篇Blog,是一个叫scum的人写的,名字叫“Zebra 条码打印机应用开发实践”,对我有些启发,在我卡在编码那里时还给他发过Email,可惜他没有回复。另外,我做成后发现他的文章里有些错误。这些后面再说。
如果你熟悉了标准的Windows打印方式,你就会发现Zebra打印图形和汉字是多么痛苦的事情。我搜索英文网站时看到一个老外把用Zebra打印图形形容成nightmare。本来以为换一些驱动程序可以解决问题,但结果还是失望的。(最终做好的程序可以不用任何驱动,只需要连上并口发码就行了。)仔细看了ZPL语言和相关知识,发现Zebra设计的还是不错的,32位RISC处理器;可接FLASH卡和PCMCIA卡;全部ASCII字符的命令,使用并口或串口发送命令,可以轻易的连接工控设备;强大的条码和RFID功能;等等。但总体觉得Zebra的DOS特征很明显,如,不具备USB连接功能;8.3的文件名命名方式;等。总的来说,如果你只是打印条码、英文和数字,那么Zebra是很好的选择。
在网上看了半天,发现要打印汉字和图形,可以由下面几种解决方案:
1. 加汉字卡
这是最傻瓜的解决方法了。但1是预算不允许,2是不够灵活。Pass。
2. 使用专用的条码软件
这里推荐Codesoft,使用方便,效果一流。但我们要开发专用软件,只能pass。
3. 使用Fnthex32.dll
如同上面说的,调用GETFONTHEX取得汉字的HEX编码,然后使用ZPL的~DG命令打印。不错的方案,也有现成的例子,但图形怎么办呢?pass。
4. 统一图形打印方式
这是我最终的使用方法,也是上面提到的scum的方法,原理其实和3一样。只是这里把要打印的标签统一按HEX图形编码,再打印。绝对的灵活,效果也好,使用并口速度也没问题。好吧,开始。
我们已有的绘图软件是一个类似微软Visio的绘图软件。它可以任意插入图片,图形,文字并设定各种格式。在用户使用Zebra打印时,我先在内存中打印成Bitmap,然后针对这个Bitmap进行编码,编码后使用ZPL命令发给打印机进行打印。
内存Bitmap
这个是打印的基础,使用Window GDI就好了。有一点需要说明,我生成的Bitmap是24-bit,96DPI(dot per inch)的,Z4M Plus一般使用8dpm(dot per mm),如果换算一下就是203DPI,这也是Z4M Plus的规格(当然也有300DPI的规格)。这样的话,Bitmap的分辨率只有打印机的一半,所以,你如果想打印大小合适的话,你的Bitmap大小应该是打印大小的两倍。记住这点,这是我琢磨了很久才想通的。只有这样,图像的每个dot才可以和打印机的每个dot对应起来,这样,你就可以精确的控制打印机每个打出来的点了。
图形的HEX编码
在这里卡了一天,ZPL里写的比较清楚,但是它是针对以毫米为单位的图形的,而我们在内存中的Bitmap是像素pixel,即dot。因为只是黑白打印,所以每个点的状态其实就是2种,要么黑,要么白,这样,每个点状态用一个bit来表示就行了(0是白,1是黑)。一个字节可以表示8个点。这个字节的高低4bit分别代表2个数字,用16进制就是0-F,而编码最终是将每个字节的两个数用ASCII码来显示,即字符的‘0’到‘F’。因为一个字节只能显示一个ASCII字符,所以编好的码需要2倍图形字节的长度。举个例子来说,一个图形只有8个点,前4个为白,后4个为黑,则第一步编码出来为一个字节,字节的8位是00001111,再编码成16进制的ASCII码后,成为2个字节,即字符‘0’‘F’。
打印
编码完成后,按照ZPL中的格式,发送~DG命令下载图形编码至Zebra机,然后使用^XG打印就行了。举体语法可以参考ZPL。计算总字节数和行字节数的方法可以参考ZPL,上面提到的scum的Blog,这里有些问题。按照他的算法,图片长度有时会超出界限,所以打印机会报错。
进阶问题
因为打印机打印的顺序的关系,按正常图形编码打印出来的内容是上下颠倒的,需要先将内存Bitmap上下颠倒后编码。
黑白阈值问题,一个点的RGB值可以是黑RGB(0,0,0)和白RGB(255,255,255)之间的任意数,对于一个彩色的像素点,它的颜色打出来到底是白还是黑呢?这里可以多做一些文章,对于文字部分,我取了较大的阈值,而对于图形部分,取了较小的阈值,这样打出来的效果好一些。
上面是我这次使用Zebra打印及开发的心得,我觉得这是一种较完美的解决方法。罗罗嗦嗦写了这么多,希望对大家有所帮助。所有代码使用VC编写,由于涉及公司制度,代码不便公开。
各位同好有问题可以发邮件给我[email protected]。也希望能有人想出更好的解决方案。
2006-11-9