最近这几天在测试DataMAx-I-4208采用DPL[Developer Programm Language]指令方式进行遇到诸多问题.解决这个问题过程中也是不断打印测试得到验证.今天早上用程序批量打印发先DAtaMax打印出来的条码效果和ZeBar斑马没什么区别.有人也询问很多采用DPL打印细节问题 就此对C#控制DAtaMAx指令DPL打印条码中遇到问题进行总结一下.
首先在讲遇到问题前搞明白我们要打印一个Code128格式的条码需要具体控制什么因素? 知道我们要在程序中要做什么 这很重要.DataMax发送DPL指令给打印机Code128条码:
打印一条Code128条码通过串口通信向打印机DataMax发送DPL指令打印. 首先要建立串口连接,同时要知道DPL中关于Code128条码打印指令语法.剩下就是条码位置 等细节调试问题. 具体总结如下:
<1>DPL中打印Code128指令语法
<2>DPL指令中控制BarCode和文本 宽度和高度
<3>DPL设置条码打印在底板上初始位置X,Y
<4>采用密尔值控制DPL中条码宽高比例.
<5>Code128条码格式控制
分析好问题,我们在项目采用是界面先建立打印模板:
打印系统条码数据时指定不同的打印模板:
后台程序自动解析打印模板和打印数据称DataMax支持的DPL指令方式 再发送给打印机批量打印.整个流程:
在上一篇中C#控制DataMax打印机问题总结中提到.Code128基本打印指令:
1: //Code128 DPL手册上打印指令 2: <STX>L 3: D11<CR> 4: 1E000000015010001234567890<CR> 5: 121100000000100Barcode E<CR> 6: E |
在DPL手册Code128基本能看到基础语法:
<STX>L对应DPL语法特定打印标识头, 如果直接通过串口工具发送给打印机 则不执行 测试发现需要把<STX>转换成16进制ACII码格式.
<D11>用来设置设置条码中平均的英寸范围内每个打印点宽度和高度. 类似打印DAtaMAx-i-4208对饮DPI203 则每英寸的打印点DOT 固定为8个,在DPL手册中设置语法:
在说明我可以看出打印机为203DPI的Dot点设置默认为D22. DWH语法能够设置的值组合总共有6个.来调节条码宽度.
第三行是核心打印条码的指令:
- //核心打印条码DPL指令 分为两部分
- 1E0000000150100 01234567890<CR>
如上清晰看出大概分为两部分. 前一部分是打印条码Code128格式字符串, 后面一部分则是条码中指定负载数据.其实如果你进一步深入会问: 不同条码间格式如何定义的?后来我翻遍整个DPL手册终于在一个小角落[150页]找到相关说明:
对打印整个条码指令进行结构拆解:
1E0000000150100 这端标识头字符串代表什么意思?继续进行拆解发现:
这时是否有些彻底明白了吧那一段代码具体代表什么意思.如下我会演示用C#发送DPLCode 128打印条码.整个过程,.在上篇中C#控制DataMax打印机问题总结.提到<STX>标识指令头转换16进制问题.
这时转换后16进制字符串,我们通过ASII16进制修改工具查看一下这个字符16进制码:
经测试发现<STX>对应16进制码为: 3C 53 54 58 3E . ok 到此在C#程序把程序拼接时发现 把这些16进制发送给打印机依然无法识别.后来找到串口工具.发现文本中拷贝进入成功打印:
发现DAtaMAx打印机识别则是<STX>转换16进制后指令字符是 ,既然有了有了<STX> 16进制编码我们进行反编译字符:
- //格式化字符指令头<STX>
- //Author:chenkai DAta:12/08 11 AM
- protected override string Leading()
- {
- #region 转16进制数据
- StringBuilder getbuilder = new StringBuilder();
- string getconverstr = "<STX>";
- char[] values = getconverstr.ToCharArray();
- foreach (char getchar in values)
- {
- int value = Convert.ToInt32(getchar);
- getbuilder.AppendFormat(String.Format("{0:X}", value));
- }
- #endregion
- this.StartStr = "<STX>".ToString();//3c 53 54 58 3E[16进制结果一直 无打印效果]
- string teststr = "EF BB BF 02";
- #region 16进制转字符串
- StringBuilder getAsibuilder = new StringBuilder();
- string[] spiltstr = teststr.Split(' ');
- string[] charstr = new string[spiltstr.Length];
- int count = 0;
- foreach (string hex in spiltstr)
- {
- int value = Convert.ToInt32(hex, 16);
- string stringValue = Char.ConvertFromUtf32(value);
- //回归字符
- char charValue = (char)value;
- charstr[count] = charValue.ToString();
- count++;
- getAsibuilder.AppendFormat(charValue.ToString());//测试发现 最后一位16ASII码即为有效字符[Fuck]
- }
- #endregion
- return charstr[charstr.Length - 1] + "L" + "\n";//D11<CR>\n";//[测试成功 但每次出现WebServer重启现象]
- }
经过对<STX>16进制编码进行反编译成字符发现最后一个16进制码3E对应就是打印识别特殊字符 . ok至此第一步让DataMAX打印机识别DPL指令.如下在来解决涉及BArcode 128在打印中涉及具体问题.
首先来看如何在利用DPL指令方式控制BarCode在打印中初始位置X,Y: 在打印中如果想知道打印元素对应的方位坐标则需要知道目前打印机对坐标系统设置对应关系:
打印机中不同的坐标系统.同一个元素所在坐标位置值则不同.类似坐标系统A中:条码对应XY坐标也不同:
根据DPL中说明DAtaMAx坐标为A方案.那么如何来通过DPL指令来控制条码在纸带上初始位置? 在DPL文档中仔细研究发现设置BArCode初始位置属性时Row OffSet和Column OFFset 分别对应语法:
基本语法为R0015,则设置在纸带上初始X坐标位置15点, 值的范围[0-9999],对应格式必须是4位数作为标识,Column Offset则基本雷同.不在赘述.添加了初始化位置DPL指令如下:
- //设置初始位置DPL指令 chenkai
- L
- R0044<CR>
- C0015<CR>
- D11<CR>
- 1E000000015010082001590000000013324<CR>
- E
从上可以看出对应初始坐标为X:y=44:15.程序中控制坐标位置格式000R:
- //格式化初始打印位置数据 chenkai
- public string ConvertDataFormat(float getvalue)
- {
- string converstr = string.Empty;
- if (!string.IsNullOrEmpty(getvalue.ToString()))
- {
- //Convert Float to int type
- string getfromtint = Convert.ToInt32(Math.Round(getvalue)).ToString();
- if (4 - getfromtint.Length > 0)
- {
- int getlength = 4 - getfromtint.Length;
- for (int count = 0; count < getlength; count++)
- {
- getfromtint = "0" + getfromtint;
- }
- converstr = getfromtint;
- }
- else
- {
- //长度超过或等于格式长度4
- if (4 - getfromtint.Length == 0)
- converstr = getfromtint;
- else
- {
- converstr = string.Empty;
- throw new EquipmentException("打印位置超过本地打印机设置 设置小于等于4位数");
- }
- }
- }
- return converstr;
- }
调用控制XY坐标:
- //设置初始打印Row OffSet 位置值
- string topstr = this.ConvertDataFormat(top);
- string leftstr = this.ConvertDataFormat(left);
- //设置初始打印Column OffSet 位置值
- getbuilder.AppendFormat("R{0}<CR>\n", topstr);
- getbuilder.AppendFormat("C{0}<CR>\n", leftstr);
如下在关注条码宽度设置,在图一中我们对条码设置一个属性值叫密尔 即条码宽度单位.在测试ZeBar打印计算ZPL中计算宽度是每密尔对应0.25CM. 但是在DPL设置则不同,单一单位区域内打印点DOt数量是不变的,只有设置DOt的高度和宽度才能设置条码外在宽度效果.203DPI 对应每英寸8个点Dot. DPL如何来设置每个点的Width和Height:具体语法格式
D11是默认值,针对300、400 600DPI打印机,DAtaMAx-i-4208的DPi为203,则对应的设置为D22. 在界面中密尔值范围8-17共10个值:
10值范围对应可以设置的比例关系为6个: 分别为1:1 /1:2/1:3/2:1/2:2/2:3. C#中进行范围指定控制:
- #region 设置密尔值.
- string miwidth="1", miheight="1";
- int barLineWidth = PubMethod.ToInt(detailtmp.BARLINEWIDTH);
- int midvalue = barLineWidth;
- if (barLineWidth < 10)
- {
- //Default Code128 Bint
- miwidth = "1";
- miheight = "1";
- }
- else if (barLineWidth >= 10 && midvalue < 12)
- {
- miwidth = "1";
- miheight = "2";
- }
- //密尔值设置BarCode 宽高比例关系.
- //DPL使用Dot 在Inch中密度在决定宽高. 不能直接设置 值范围Width[1-2] Height[1-3]
- //DAtaMAx中DPi203 默认值 为D22 Code 128设置Defaul D11
- string setLocation="D"+miwidth+miheight;
- getbuilder.AppendFormat(setLocation+"<CR>\n");
- #endregion
如果采用默认的D11设置发现打印出来效果 总体条码宽度或高度过小.需要对条码宽高进行重新设置.在Code128语法命令有一段说明很重要:
其中明确提到第四个字符用来设置条码宽度,从第五个字符串到第七位设置条码高度值. Height[0-999] C#则需要凭借字符串方式来组合DPL指令:
- #region 处理条码宽高比例
- //BarCode设置宽高比例需要Header FrmatString设置 宽第四个字符 高 第五至第七个字符串
- //Width[0-9]-Common[0-4] height[0-999]-Common[32-45]
- string widthstr = string.Empty;
- string heightstr = string.Empty;
- //元素在打印效果中宽高
- width = (detailtmp.ENDX - detailtmp.BEGINX);
- height = (detailtmp.ENDY - detailtmp.BEGINY);
- if (this.Template != null)
- {
- widthstr = ((int)width/100).ToString();
- heightstr =this.FormatBarCodeHeight(((int)height-25).ToString());
- if (Convert.ToInt32(widthstr) > 9)
- widthstr = "9";
- else if (Convert.ToInt32(widthstr) == 0)
- widthstr = "1";
- }
- #endregion
- getbuilder.AppendFormat("1E0{0}{1}00150100{2}\n","1",heightstr,barcode);//剔除<CR>
至此从程序发给DAtaMAx最终打印DPL指令为:
- //最终DPL指令
- L
- D22<CR>
- R0044<CR>
- C0015<CR>
- 1E01032001501008200745869542876<CR>
- 121100000000100Barcode T<CR>
- E
最终控制打印效果[居中设置]:
最后关于<CR>如果在传入条码值时最好去掉 在指令中有时会把CR作为字符串打印条码数据中.
本文转自chenkaiunion 51CTO博客,原文链接:http://blog.51cto.com/chenkai/763875