最近两周时间一直在测试系统涉及条码打印问题,由于原来系统采用通用驱动方式统一Intermac/ZeBar/DataMAx打印.但在处理DataMax打印效果是出现打印条码出现锯齿散射状,导致扫描枪无法识别.

我拿到打印机型号DataMax-I-4208热敏打印型号,坦白说解决问题过程是很折磨人的,一方面源自这方面官方提供资源和打印实例有限,另外一方面设计到设备参数具体调试, 针对C#控制DataMax-I-4208一系列问题解决方法作如下总结:

<1>DataMax打印Code128条码出现锯齿状

 C#控制DataMax打印机问题总结-风君雪科技博客

首先要明白一个概念:DPI [Dots Per Inch]的缩写。每英寸所打印的点数或线数,用来表示打印机打印分辨率。dpi是指单位面积内像素的多少,也就是扫描精度,目前国际上都是计算一平方英寸面积内像素的多少。dpi越小,扫描的清晰度越低.

DataMax打印机型号:DataMax-I-4208-203DPI

当我们在默认情况下把系统生成的条码BMP格式图片通过驱动方式发给打印机.采用DPI是当前本地系统屏幕默认显示的DPI值一般是96DPI. 这样导致打印机值不一致出现就 锯齿 模糊打印效果: C#中如何设置修改DPI:

   1:   //设置DPI决定属性值与DataMAx必须相符203DPI 必须一致
   2:   var setdpiimg = (Bitmap)_DrawImg;
   3:   if (setdpiimg != null)
   4:      {
   5:          setdpiimg.SetResolution(203f, 203f);
   6:      }

.csharpcode, .csharpcode pre { font-size: small; color: rgba(0, 0, 0, 1); font-family: consolas, “Courier New”, courier, monospace; background-color: rgba(255, 255, 255, 1) }
.csharpcode pre { margin: 0 }
.csharpcode .rem { color: rgba(0, 128, 0, 1) }
.csharpcode .kwrd { color: rgba(0, 0, 255, 1) }
.csharpcode .str { color: rgba(0, 96, 128, 1) }
.csharpcode .op { color: rgba(0, 0, 192, 1) }
.csharpcode .preproc { color: rgba(204, 102, 51, 1) }
.csharpcode .asp { background-color: rgba(255, 255, 0, 1) }
.csharpcode .html { color: rgba(128, 0, 0, 1) }
.csharpcode .attr { color: rgba(255, 0, 0, 1) }
.csharpcode .alt { background-color: rgba(244, 244, 244, 1); 100%; margin: 0 }
.csharpcode .lnum { color: rgba(96, 96, 96, 1) }

DPI是每英寸点数, 如果DPI的值过低,则图片在每英寸点数较少 位图打印后效果则比较模糊. 设置DPI值变大后图片则明显变小,清晰度变高,发现打印条码扫描枪能识别,至于大小可以通过移位替换方式高质量缩放的进行转换:C#控制代码

   1:   //缩放控制[高质量]
   2:    Bitmap getbitmap = new Bitmap(300,400);
   3:    Graphics newgra = Graphics.FromImage(getbitmap);
   4:   
   5:    //插值算法质量控制
   6:     newgra.InterpolationMode = InterpolationMode.HighQualityBicubic;
   7:     newgra.DrawImage(DrawImg,new Rectangle(0,0,DrawImg.Width,DrawImg.Height),
   8:     new Rectangle(0,0,getbitmap.Width,getbitmap.Height),GraphicsUnit.Pixel);
   9:     newgra.Dispose();
  10:   
  11:     return getbitmap;

 

如上控制图片大小设置Width:300PX[像素] Height:400PX[像素] 可以自定义设置.

C#进行打印输出控制后基本能够完整打印: 效果:

C#控制DataMax打印机问题总结-风君雪科技博客


.csharpcode, .csharpcode pre { font-size: small; color: rgba(0, 0, 0, 1); font-family: consolas, “Courier New”, courier, monospace; background-color: rgba(255, 255, 255, 1) }
.csharpcode pre { margin: 0 }
.csharpcode .rem { color: rgba(0, 128, 0, 1) }
.csharpcode .kwrd { color: rgba(0, 0, 255, 1) }
.csharpcode .str { color: rgba(0, 96, 128, 1) }
.csharpcode .op { color: rgba(0, 0, 192, 1) }
.csharpcode .preproc { color: rgba(204, 102, 51, 1) }
.csharpcode .asp { background-color: rgba(255, 255, 0, 1) }
.csharpcode .html { color: rgba(128, 0, 0, 1) }
.csharpcode .attr { color: rgba(255, 0, 0, 1) }
.csharpcode .alt { background-color: rgba(244, 244, 244, 1); 100%; margin: 0 }
.csharpcode .lnum { color: rgba(96, 96, 96, 1) }

打印基本OK.

<2>DataMax-I-4208 DPL指令方式打印

当我们通过程序通用驱动方式去打印,发送给打印机是一张位图Bitmap图片,输出打印. DataMax DPL方式则更直接通过指令编码实现对条码打印精确控制. DPL编程时DAtaMax定义一套打印指令 完全不同InterMac和Zebar[斑马]打印机. 如何获得DPL Program HandleBook 编程手册:

首先找到驱动盘,读取驱动内容发现:

C#控制DataMax打印机问题总结-风君雪科技博客

运行Do应用程序:

C#控制DataMax打印机问题总结-风君雪科技博客

找到指定打印机类型: Data Max-I系列 即I-Class:

C#控制DataMax打印机问题总结-风君雪科技博客

找到开发人员手册PDF:

C#控制DataMax打印机问题总结-风君雪科技博客

红色标识是驱动程序, 绿色标识就是我们需要的Programmer HandleBook 开发人员手册即DPL指令集如果你没有驱动盘则可以如下链接方式下载DPL完整指令集:

DataMax-I-Class DPI指令集PDF下载

原始的DPL 指令集是全英的,总页数多大350多页, 我个人经验是 针对这个DPL Programmer PDF 文档不要过于盲目的去查看, 主要是因为内容太多,而且大多数你都用不到, 所以在看这份文档前 仔细的阅读以下目录会很容易找到你想要东西, .这点会让你事半功力倍:

在DPL手册查找指令前 要知道我们我们需要指令控制什么因素: 针对BarCode Code 128格式做了大概分析影响因素如下:

<1>Print Speed打印速度[如果不是特别快或特别慢采用默认]

<2>Label Location 条码坐标位置

<3>Chinese Control 中文字符处理 –默认情况打印中文是出现乱码 ??? 需要额外配置

<4>Label Value 条码值

<5>Label Frmat 条码打印格式

既然有了需求 剩下工作也是不断查找打印指令 测试输出效果一个过程: 现在我们打印一个最为基本字符串大概来看一下DPL 指令格式 :

   1:  //打印一个字符串DPL指令
   2:  <STX>L
   3:  D11<CR>
   4:  1T0000000150100ABCDEF<CR>
   5:  121100000000100Barcode T<CR>
   6:  E

.csharpcode, .csharpcode pre { font-size: small; color: rgba(0, 0, 0, 1); font-family: consolas, “Courier New”, courier, monospace; background-color: rgba(255, 255, 255, 1) }
.csharpcode pre { margin: 0 }
.csharpcode .rem { color: rgba(0, 128, 0, 1) }
.csharpcode .kwrd { color: rgba(0, 0, 255, 1) }
.csharpcode .str { color: rgba(0, 96, 128, 1) }
.csharpcode .op { color: rgba(0, 0, 192, 1) }
.csharpcode .preproc { color: rgba(204, 102, 51, 1) }
.csharpcode .asp { background-color: rgba(255, 255, 0, 1) }
.csharpcode .html { color: rgba(128, 0, 0, 1) }
.csharpcode .attr { color: rgba(255, 0, 0, 1) }
.csharpcode .alt { background-color: rgba(244, 244, 244, 1); 100%; margin: 0 }
.csharpcode .lnum { color: rgba(96, 96, 96, 1) }DPL文档并没有对打印指令的语法格式进行说明,大多在说如何去设置 采用什么样指令, 说以在大概无数次测试中我也大概掌握DPL打印指令的基本语法格式 分享给各位[可能不准确]:

<STX>L:指定的是打印类型 <STX>L 自定打印一个条码

Dll:则是对打印类型下更一步细分类似条码 则分为Code 128 UPC-E 或二维码等

<CR>: 类似C#每行代码的; 指定当前本行指令结束符

E: 则是指定整段指令结束符 也就是说E 字符后面打印机自动不读取识别的.

通过串口发送给打印机 指令完全正确 但DataMax-i-4208完全没有反映,后来我联系厂商才明白:

<STX>打印指令头需要需要转换16进制打印机才能识别 转换后在TXT文本效果:

C#控制DataMax打印机问题总结-风君雪科技博客

ok.通过串口工具发送指令给打印机 DataMax-i-4208终于开始响应 打印效果:

C#控制DataMax打印机问题总结-风君雪科技博客

打印成功 DPL指令方式唯一不用担忧的条形码的质量 很清晰,指令这种模式做一个简单类比 打印机就类似一个ATM取款机,不同的人携带不同的银行卡即对应不同DPL 打印指令就能取到不同货币美元 RMB等即对应打印结果.

而驱动方式 则前提是必须通过程序方式生成一张完整清晰的图片, 数据发送给打印机 打印采用自己设置和字库进行画出来打印.

那么测试指令没有问题如何通过C#编程方式发给打印机,再来看如何在编程中控制条码的位置:

条码打印在打印纸都有一个坐标位置对应X /y  很多人对于DPL指令如何条码位置都很迷茫, 经过多方验证得多结论 DPL设置:

Row OffSet 设置对应行起始位置就X坐标位置

Column Offset 设置对饮列起始坐标位置 即Y坐标位置

还有两个参数:

ROW ADJUST(行调整) 以点为单位对行起始位置(ROW OFFSET)进行微调

COLUMN ADJUST(列调整) 以点为单位对列起始位置(COLUMN OFFSET)进行微调

现在有了DPL参数名称 我要告诉你不要就直接跑到 DPL 350页大文档里去一点点去翻 给你一个直接简单方式 利用PDF的查找快速定位你要找内容 虽然觉得这没什么 可是我要告诉你这种简单效果 在一个非母语的文档 效果还是非常好的:

C#控制DataMax打印机问题总结-风君雪科技博客

详细语法说明:

C#控制DataMax打印机问题总结-风君雪科技博客

其他设置基本雷同,那么在C#编程的话就要DPL指令格式限制问题. 类似我们制定X坐标即Row Offset的值 语法是R0037<CR>结束.首先X坐标的值范围是0-9999,而且DPL规定格式必须是4位数. 也就是说类似设置X坐标为5  DPL标准识别格式:R0005<CR> C#进行控制:

   1:        /// <summary>
   2:        /// 处理数据宽高格式0000 打印指令0010
   3:        /// </summary>
   4:        public string ConvertDataFormat(float getvalue)
   5:        {
   6:            string converstr = string.Empty;
   7:            if (!string.IsNullOrEmpty(getvalue.ToString()))
   8:            {
   9:                //Convert Float to int type
  10:                string getfromtint = Convert.ToInt32(getvalue.ToString()).ToString();
  11:                if (4 - getfromtint.Length > 0)
  12:                {
  13:                    for (int count = 0; count < 4 - getfromtint.Length; count++)
  14:                    {
  15:                        getfromtint = "0" + getfromtint;
  16:                    }
  17:                    converstr = getfromtint;
  18:                }
  19:                else
  20:                {
  21:                    //长度超过或等于格式长度4
  22:                    if (4 - getfromtint.Length == 0)
  23:                        converstr = getfromtint;
  24:                    else
  25:                    {
  26:                        converstr = string.Empty;
  27:                        throw new EquipmentException("设定打印元素初始打印位置超过本地打印机设置 设置小于等于4位数");
  28:                    }
  29:                }
  30:            }
  31:            return converstr;
  32:        }

.csharpcode, .csharpcode pre { font-size: small; color: rgba(0, 0, 0, 1); font-family: consolas, “Courier New”, courier, monospace; background-color: rgba(255, 255, 255, 1) }
.csharpcode pre { margin: 0 }
.csharpcode .rem { color: rgba(0, 128, 0, 1) }
.csharpcode .kwrd { color: rgba(0, 0, 255, 1) }
.csharpcode .str { color: rgba(0, 96, 128, 1) }
.csharpcode .op { color: rgba(0, 0, 192, 1) }
.csharpcode .preproc { color: rgba(204, 102, 51, 1) }
.csharpcode .asp { background-color: rgba(255, 255, 0, 1) }
.csharpcode .html { color: rgba(128, 0, 0, 1) }
.csharpcode .attr { color: rgba(255, 0, 0, 1) }
.csharpcode .alt { background-color: rgba(244, 244, 244, 1); 100%; margin: 0 }
.csharpcode .lnum { color: rgba(96, 96, 96, 1) }

针对<STX>打印标头转换 16进制控制:

   1:        /// <summary>
   2:        /// Start Print CodeChar 指令:"<STX>L" 
   3:        /// 转换成16进制AS#格式
   4:        /// </summary>
   5:        protected override string Leading()
   6:        {
   7:            #region 转16进制数据
   8:            byte[] bytes = System.Text.Encoding.Default.GetBytes("<STX>L");
   9:            string reStr = string.Empty;
  10:            foreach (byte b in bytes)
  11:            {
  12:                short st = (short)(b - '\0');
  13:                reStr += st.ToString("x") + "%";
  14:            }
  15:            #endregion
  16:            return reStr;
  17:        }

.csharpcode, .csharpcode pre { font-size: small; color: rgba(0, 0, 0, 1); font-family: consolas, “Courier New”, courier, monospace; background-color: rgba(255, 255, 255, 1) }
.csharpcode pre { margin: 0 }
.csharpcode .rem { color: rgba(0, 128, 0, 1) }
.csharpcode .kwrd { color: rgba(0, 0, 255, 1) }
.csharpcode .str { color: rgba(0, 96, 128, 1) }
.csharpcode .op { color: rgba(0, 0, 192, 1) }
.csharpcode .preproc { color: rgba(204, 102, 51, 1) }
.csharpcode .asp { background-color: rgba(255, 255, 0, 1) }
.csharpcode .html { color: rgba(128, 0, 0, 1) }
.csharpcode .attr { color: rgba(255, 0, 0, 1) }
.csharpcode .alt { background-color: rgba(244, 244, 244, 1); 100%; margin: 0 }
.csharpcode .lnum { color: rgba(96, 96, 96, 1) }

获取字体方法:

   1:       //字体设置
   2:        using System.Runtime.InteropServices;
   3:        [DllImport("fnthex32.dll", CharSet = CharSet.Ansi)]
   4:        public static extern int GETFONTHEX(
   5:               string chnstr,
   6:               string fontname,
   7:               int orient,
   8:               int height,
   9:               int width,
  10:               int bold,
  11:               int italic,
  12:            StringBuilder cBuf);

.csharpcode, .csharpcode pre { font-size: small; color: rgba(0, 0, 0, 1); font-family: consolas, “Courier New”, courier, monospace; background-color: rgba(255, 255, 255, 1) }
.csharpcode pre { margin: 0 }
.csharpcode .rem { color: rgba(0, 128, 0, 1) }
.csharpcode .kwrd { color: rgba(0, 0, 255, 1) }
.csharpcode .str { color: rgba(0, 96, 128, 1) }
.csharpcode .op { color: rgba(0, 0, 192, 1) }
.csharpcode .preproc { color: rgba(204, 102, 51, 1) }
.csharpcode .asp { background-color: rgba(255, 255, 0, 1) }
.csharpcode .html { color: rgba(128, 0, 0, 1) }
.csharpcode .attr { color: rgba(255, 0, 0, 1) }
.csharpcode .alt { background-color: rgba(244, 244, 244, 1); 100%; margin: 0 }
.csharpcode .lnum { color: rgba(96, 96, 96, 1) }

对于中文字体也就是Chinese Simple[中文简体格式]是双字节 在DataMax中, 默认是不支持中文,类似我们把打印指令换成汉字 打印结果是出来字符乱码 ??? 这是什么问题. 我查了DAtaMAx官方对Chinese simple 中说明发现 如果需要DataMax打印中文则需要安装字库或在打印机上安装中文字卡才能识别. 如果不安装字卡 还有另外一种方式 采用第三方控件方式支持中文打印:

标准控件:http://www.51barcode.com/downloads/list.asp?id=82  或者可通过第三方条码软件控件实现如Codesoft等

C#识别中文字符判断:

   2:        /// 验证是否是中文字符
   4:        public bool IsChinese(string getvalue)
   5:        {
   6:           return System.Text.RegularExpressions.Regex.IsMatch(getvalue, @"[\u4e00-\u9fa5]");
   7:        }

DPL手册中对Chinese Simple中文简体打印方式做了详细说明 详见DPL PDF文档手册285/250/254页:

C#控制DataMax打印机问题总结-风君雪科技博客

针对DataMax中文打印问题 DPL手册中给了一个打印汉字 盒 的例子 可惜这个例子 我经过N多次尝试 通过串口发送打印DPL 始终没能成功使用这个例子. 后来详细研究这个DPL 文件.发现针对中文设置的语法其实很简单:

   1:  //打印汉字DPL语法
   2:  <STX>L<CR>
   3:  D11<CR>
   4:  ySPM<CR>
   5:  1911S0003100010P020P015 Chinese Available in GB r Set<CR>
   6:  yUGB<CR>
   7:  1911UC001200145P040P030<BA><D0><00><00><CR>
   8:  1911UC001200190P040P040<BA><D0><00><00><CR>
   9:  1911UC001200250P040P050<BA><D0><00><00><CR>
  10:  1911UC001200320P040P060<BA><D0><00><00><CR>
  11:  E

.csharpcode, .csharpcode pre { font-size: small; color: rgba(0, 0, 0, 1); font-family: consolas, “Courier New”, courier, monospace; background-color: rgba(255, 255, 255, 1) }
.csharpcode pre { margin: 0 }
.csharpcode .rem { color: rgba(0, 128, 0, 1) }
.csharpcode .kwrd { color: rgba(0, 0, 255, 1) }
.csharpcode .str { color: rgba(0, 96, 128, 1) }
.csharpcode .op { color: rgba(0, 0, 192, 1) }
.csharpcode .preproc { color: rgba(204, 102, 51, 1) }
.csharpcode .asp { background-color: rgba(255, 255, 0, 1) }
.csharpcode .html { color: rgba(128, 0, 0, 1) }
.csharpcode .attr { color: rgba(255, 0, 0, 1) }
.csharpcode .alt { background-color: rgba(244, 244, 244, 1); 100%; margin: 0 }
.csharpcode .lnum { color: rgba(96, 96, 96, 1) }

ySPM<CR>是打印语言和字体支持设置语法.  ySPM是默认设置, yUGB则对应打印中文字体 这个设置很重要. 那么我发现在DPL中并没有汉字,其实DAtaMax针对打印汉字支持格式是GBK格式编码 类似我们现在看到 汉字 盒 对应编码就是<BA><DO><OO><OO>. C#中默认字符UNICODE格式这个得注意 需要把汉字重新转码在传入DPL指令中 打印机才能识别. 打印出来结果是 4个盒字:

C#控制DataMax打印机问题总结-风君雪科技博客

在来说打印条码Code128格式 DPL指令:

   1:  //打印Code 128
   2:  <STX>L
   3:  D11<CR>
   4:  1E000000015010001234567890<CR>
   5:  121100000000100Barcode E<CR>
   6:  E

.csharpcode, .csharpcode pre { font-size: small; color: rgba(0, 0, 0, 1); font-family: consolas, “Courier New”, courier, monospace; background-color: rgba(255, 255, 255, 1) }
.csharpcode pre { margin: 0 }
.csharpcode .rem { color: rgba(0, 128, 0, 1) }
.csharpcode .kwrd { color: rgba(0, 0, 255, 1) }
.csharpcode .str { color: rgba(0, 96, 128, 1) }
.csharpcode .op { color: rgba(0, 0, 192, 1) }
.csharpcode .preproc { color: rgba(204, 102, 51, 1) }
.csharpcode .asp { background-color: rgba(255, 255, 0, 1) }
.csharpcode .html { color: rgba(128, 0, 0, 1) }
.csharpcode .attr { color: rgba(255, 0, 0, 1) }
.csharpcode .alt { background-color: rgba(244, 244, 244, 1); 100%; margin: 0 }
.csharpcode .lnum { color: rgba(96, 96, 96, 1) }

输出效果:

C#控制DataMax打印机问题总结-风君雪科技博客