基于C#在WPF中使用斑马打印机进行打印【转】
原文链接:http://ju.outofmemory.cn/entry/132476
最近在项目中接手了一个比较有挑战性的模块——用斑马打印机将需要打印的内容打印出来。苦苦折腾了两天,总算有所收获,就发到网上来骗骗分数-_-||
项目中使用的打印机型号为GX430t的打印机,接手的时候,自己对于打印机这块儿是眼前一抹黑,啥都不知道。没办法一步步来。
首先尝试使用WPF中的PrintDialog里面的PrintVisual和PrintDocument方法,打印机是一点反应都没有,最后得到的结论是:斑马打印机不支持MS的XPS文档格式,所以使用WPF来排版后进行驱动打印就不要想了,不可能!!!这条路到这里就断了。
然后就想到有没有SDK可以直接进行打印,就找到了斑马打印机的技术支持,还是个妹子,我提了一下,妹子说没有开发包可以用,然后就贴了一个网址给我,网址就是这条:http://blog.csdn.net/ldljlq/article/details/7338772。可能我的水平有限,反正我感觉啰啰嗦嗦一大堆,实际的东西没多少,不过关键点倒是提了出来使用图像或者指令进行打印。我首先想到的是使用指令进行打印,就去找妹子要了Zebra的技术手册,一打开就吓尿了,尼玛1000+页的东西,我只是用一下打印机又不是去帮你们打印机开发驱动,当时心里那个抵触啊。但是没办法,得看呐,就仔细看了一些,找到打印的指令试了试,有东西能打出来,当时感觉挺满足的。唯一比较纠结的就是打印机支持的字体和字体本身的一些设置,比如粗体、斜体等等,资料里面没找到,然后去问了下斑马的技术支持,得知斜体字可以打,但是不清楚有没有对应的指令。没办法,项目里面用的字体多,还有各种斜体神马的,玩WPF的都知道,那么多属性一个个设置下来,光字体类型斑马就搞不定。
既然直接使用指令打印行不通就考虑使用图像打印,图像又跟多媒体挂钩了,尼玛真是够了。因为玩过链接里面的仁兄提到的获取打印模板的命令的方法。就是在安装好打印机驱动后,手动创建一个新的本地端口并在打印机设置中将打印机端口设为新建的端口。使用Zebra的创建模板的软件创建好你想要的东西,然后打印,就能在你创建的端口文件中得到你想要的指令序列(其实,模板里面使用的就是图像打印)。指令序列有了,对照手册查询相应的指令就能得到你想要的东西。
这里说的图像打印并不是我们平时说的位图或者矢量图,手册里面说是叫GRF格式的图像,仔细研究了一下,其实就是缀着这么个名字而已,里面需要的数据其实就是图像矩阵。而且图像矩阵中的像素表示法是:一个字节表示8个像素,也就是一个bit位(0或1)表示一个像素的颜色(黑或白)。看到这里脑子里有了思路:将要打印的内容进行排版->将排版好的数据转换成位图->将位图中的数据,根据需要转换成指令中要求的格式->交给打印机打印。这样一来就没有什么打印机对字体本身的限制了。思路有了,剩下的就是方法。
排版比较简单,这个玩过自定义控件的人都知道,使用DrawingVisual可以构建自己想要的Visual。然而将Visual转换成位图就难住我了,纠结了一个下午终于从网上找到了一个东西—-RenderTargetBitmap。这个类可以将你的Visual转换成位图。
下面就是将位图数据转换成指令中的图像数据,咳咳,数学不够好,在分析数据的时候搞错了一个地方让我纠结了好长时间,不过总体来说还是解决了。说一下思路:
- 通过RenderTargetBitmap类的CopyPixels方法将像素数据拷贝出来。因为这个位图创建的时候只是作为一个中间的过程,所以格式可以随便选,我是选择了PixelFormats.Pbgra32格式,比较简单。这个格式的图像像素是用4个字节表示,依次为:Blue、Green、Red、Alpha。拷贝的时候,作为缓冲区的数组需要将长度设为像素数的4倍。
- 像素拷贝的时候会有一个“跨距”的东西。这个表示的是图像中一行中数据的字节数,必须为4的倍数。也就是取大于或等于真实值的最小的能够被4整除的数值。
- 获取到数据就可以对数据进行整理了,遍历整个数组,如果当前像素的颜色值不为白色或者透明色就将目标数组中的bit位之一(目标数组中用bit位表示对应像素的值)
- 将获得的数组转换成string串,然后将该串插入到指令序列中相应的位置就得到对应的指令。
说到这里其实说的也差不多了,顺便说下,WPF里面的打印支持真的很强大,给打印机传递指令的操作也很简单,具体见下面的代码。
这里是源代码:
/// <summary>
/// 获取绘制Visual的命令
///
</summary>
/// <param
name=”visual”>要获取的Visual</param>
/// <param
name=”pixelWidth”>像素宽度</param>
/// <param
name=”pixelHeight”>像素高度</param>
/// <param
name=”dpiX”>横向dpi</param>
/// <param
name=”dpiY”>纵向dpi</param>
/// <param
name=”offsetX”>横坐标偏移量,单位为像素数</param>
/// <param
name=”offsetY”>纵坐标偏移量,单位为像素数</param>
///
<returns></returns>
private string GetPrintZPL(Visual
visual, int pixelWidth, int pixelHeight, double dpiX, double dpiY, int offsetX,
int offsetY)
{
string ret = string.Empty;//构建图片
RenderTargetBitmap bmp = new
RenderTargetBitmap(pixelWidth, pixelHeight, dpiX, dpiY, PixelFormats.Pbgra32);#if TEST //test
DrawingVisual newVisual = new
DrawingVisual();
DrawingContext dc = newVisual.RenderOpen();dc.DrawEllipse(Brushes.Black, new Pen(), new Point(bmp.Width /
2, bmp.Height / 2), bmp.Width / 2, bmp.Height / 2);
dc.Close();visual = null;
bmp.Render(newVisual);
#elsebmp.Render(visual);
#endif
byte[] datas =
new byte[bmp.PixelWidth * bmp.PixelHeight * 4];
bmp.CopyPixels(datas, bmp.PixelWidth * 4, 0);//获取图像数据
int
rowBytes = (pixelWidth + 7) / 8;
byte[] targetDatas = new
byte[rowBytes * bmp.PixelHeight];
for (int i = 0; i <
bmp.PixelHeight; i++) //数据调整,并将数据
{
for (int
j = 0; j < bmp.PixelWidth; j++)
{
byte blue = datas[i * bmp.PixelWidth * 4 + j * 4 + 0];
byte green = datas[i * bmp.PixelWidth * 4 + j * 4 + 1];
byte red = datas[i * bmp.PixelWidth * 4 + j * 4 + 2];
byte alpha = datas[i * bmp.PixelWidth * 4 + j * 4 + 3];
if (blue == 0 && green == 0 && red == 0)
{
if (alpha == 255)//alpha也是0则为透明色{
byte cur = 1;cur = (byte)(cur << (7 – j % 8));
targetDatas[i * rowBytes + j / 8] |= cur;
}
}
else
{
if (!(blue == 255
&& green == 255 && red == 255 && alpha ==
255))//全为255则表示白色
{
byte cur = 1;
cur = (byte)(cur << (7 – j %
8));
targetDatas[i * rowBytes + j / 8] |= cur;}
}
}}
ret =
string.Format(“^XA~TA000~JSN^LT0^MNW^MTT^PON^PMN^LH0,0^JMA^PR3,3~SD29^JUS^LRN^CI0^XZ~DG000.GRF,{0},{1},{2}^XA^MMT^PW260^LL0189^LS0^FT0,192^FO{3},{4},^XG000.GRF,1,1^FS^PQ1,0,1,Y^XZ^XA^ID000.GRF^FS^XZ”,
targetDatas.Length, rowBytes, BitConverter.ToString(targetDatas).Replace(“-“,
string.Empty), offsetX, offsetY);
return ret;
}
基于C#在WPF中使用斑马打印机进行打印【转】的更多相关文章
- 基于C#在WPF中使用斑马打印机进行打印【转】——不支持XPS的打印机
https://www.cnblogs.com/zhaobl/p/4666002.html
- 斑马打印机的安装调试,生成PDF
1. 我使用的斑马打印机GK888T.有问题打客服,耐心等待.售后电话4006456456得到了解决. 2. 我遇到的问题是打印一张之后指示灯变为红灯,时好时坏.解决方案,长按指示键,待指示灯连续 ...
- 吉特仓库管理系统- 斑马打印机 ZPL语言的腐朽和神奇
上一篇文章说到了.NET中的打印机,在PrintDocument类也暴露一些本质上上的问题,前面也提到过了,虽然使用PrintDcoument打印很方便.对应条码打印机比如斑马等切刀指令,不依赖打印机 ...
- C#调用斑马打印机打印条码标签(支持COM、LPT、USB、TCP连接方式和ZPL、EPL、CPCL指令)【转】
原文地址:http://blog.csdn.net/ldljlq/article/details/7338772 在批量打印商品标签时一般都要加上条码或图片,而这类应用大多是使用斑马打印机,所以我也遇 ...
- WPF中的依赖项属性
Form cnblogs 桂素伟 随着WPF的推广,不得不重新拾起WPF来,因为这块的产品越来越多. 只能跟着MSDN来学了,所以想是在这里记录下学习的过程和对知识的理解. 先从最基本的吧,依赖项属性 ...
- WPF中嵌入普通Win32程序的方法
公司现在在研发基于.Net中WPF技术的产品,由于要兼容旧有产品,比如一些旧有的Win32程序.第三方的Win32程序等等,还要实现自动登录这些外部Win32程序,因此必须能够将这些程序整合到我们的系 ...
- 斑马打印机网卡ZebraNet配置(有线)
实图: 抽象图: 说明: 1.并口,用于连接斑马打印机一端 2.网络连接状态指示灯 3.打印状态指示灯 4.测试按钮,在连接打印机的情况下,按下此键,会打印出网卡信息. 5.网线接口 按下测试按钮之后 ...
- 简单的介绍下WPF中的MVVM框架
最近在研究学习Swift,苹果希望它迅速取代复杂的Objective-C开发,引发了一大堆热潮去学它,放眼望去各个培训机构都已打着Swift开发0基础快速上手的招牌了.不过我觉得,等同于无C++基础上 ...
- WPF中的资源简介、DynamicResource与StaticResource的区别(转)
什么叫WPF的资源(Resource)?资源是保存在可执行文件中的一种不可执行数据.在WPF的资源中,几乎可以包含图像.字符串等所有的任意CLR对象,只要对象有一个默认的构造函数和独立的属性. 也就是 ...
随机推荐
- c++打开浏览器
调用外部命令 如果用默认浏览器,就调用ShellExecute(NULL, _T("open"), _T("explorer.exe"), _T("h ...
- python 学习笔记十七 django深入学习二 form,models
表单 GET 和 POST 处理表单时候只会用到GET 和 POST 方法. Django 的登录表单使用POST 方法,在这个方法中浏览器组合表单数据.对它们进行编码以用于传输.将它们发送到服务器然 ...
- c# winform DataGridView单击选中一整行,只能单选,不能选择多行,只能选择一行
设置DataGridView的属性SelectionMode为FullRowSelect 这样就使DataGridView不是选择一个字段,而是选择一整行了 设置DataGridView的属性Mult ...
- tomcat启动超时问题
当启动tomcat时候出现 Server Tomcat v6.0 Server at localhost was unable to start within 45 seconds. If the s ...
- 前台JS(type=‘file’)读取本地文件的内容,兼容各种浏览器
[自己测了下,能兼容各种浏览器,但是读取中文会出现乱码.自己的解决方法是用notepad++把txt文件编码改为utf-8(应该是和浏览器编码保持一致吧?..)] 原文 http://blog.cs ...
- 连锁机构3D指纹考勤系统解决方案
信息技术的高速发展加速了商业零售业连锁经营的信息化和全球化的进程,同时也推动了商业管理的变革.尽管人们对它的认识是被动与滞后的,但这种变革依然伴随着商业业态的转变和信息技术的发展或快或慢地在悄然进行着 ...
- HANA SQL
约束 注释 你可以给你的 SQL 语句添加注释来增加可读性和可维护性. SQL 语句中注释的分隔如下: l 双连字符“--”.所有在双连字符之后直到行尾的内容都被 SQL 解析器认为是注释. l ...
- js基础:函数表达式和函数声明
函数表达式和函数声明的区别.实际上,解析器在向执行环境中加载数据是,对函数表达式和函数声明并非一视同仁.解析器会率先读取函数声明,并使其在执行任何代码之前可用.而函数表达式,则必须等到解析器执行到它所 ...
- ubuntu服务管理
uRedhat 提供了chkconfig这个命令来管理系统在不同运行级别下的服务开启/关闭: chkconfig ServiceName on/off 并可以用chkconfig --list(两个杠 ...
- Treap
treap模板 期望复杂度为O(nlogn) 带合并的treap期望复杂度为O(nlognlogn) #include <bits/stdc++.h> ; struct tree{ int ...