C# 热敏打印机 小票打印机 打印图片
最近一直在研究并口小票打印机打印图片问题,这也是第一次和硬件打交道,不过还好,最终成功了。
这是DEMO的窗体:
下面是打印所需要调用的代码:
class LptControl { private string LptStr = "lpt1"; public LptControl(string l_LPT_Str) { LptStr = l_LPT_Str; } [StructLayout(LayoutKind.Sequential)] private struct OVERLAPPED { int Internal; int InternalHigh; int Offset; int OffSetHigh; int hEvent; } //调用DLL. [DllImport("kernel32.dll")] private static extern int CreateFile(string lpFileName, uint dwDesiredAccess, int dwShareMode, int lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, int hTemplateFile); [DllImport("kernel32.dll")] private static extern bool WriteFile(int hFile, byte[] lpBuffer, int nNumberOfBytesToWrite, ref int lpNumberOfBytesWritten, ref OVERLAPPED lpOverlapped); [DllImport("kernel32.dll")] private static extern bool CloseHandle(int hObject); private int iHandle; /// <summary> /// 打开端口 /// </summary> /// <returns></returns> public bool Open() { iHandle = CreateFile(LptStr, 0x40000000, 0, 0, 3, 0, 0); // iHandle = CreateFile(LptStr, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); if (iHandle != -1) { return true; } else { return false; } } /// <summary> /// 打印字符串,通过调用该方法可以打印需要的字符串 /// </summary> /// <param name="Mystring"></param> /// <returns></returns> public bool Write(String Mystring) { //如果端口为打开,则提示,打开,则打印 if (iHandle != -1) { OVERLAPPED x = new OVERLAPPED(); int i = 0; //byte[] mybyte = System.Text.Encoding.Default.GetBytes(Mystring); byte[] mybyte = Encoding.GetEncoding("GB2312").GetBytes(Mystring); bool b = WriteFile(iHandle, mybyte, mybyte.Length, ref i, ref x); return b; } else { throw new Exception("不能连接到打印机!"); } } /// <summary> /// 打印命令,通过参数,可以打印小票打印机的一些命令,比如换行,行间距,打印位图等。 /// </summary> /// <param name="mybyte"></param> /// <returns></returns> public bool Write(byte[] mybyte) { //如果端口为打开,则提示,打开,则打印 if (iHandle != -1) { OVERLAPPED x = new OVERLAPPED(); int i = 0; return WriteFile(iHandle, mybyte, mybyte.Length, ref i, ref x); } else { throw new Exception("不能连接到打印机!"); } } /// <summary> /// 关闭端口 /// </summary> /// <returns></returns> public bool Close() { return CloseHandle(iHandle); } }
因为我们这里主要是打印条形码和二维码,所以以条形码和二维码为例,写了一个小的调用程序(这里把打印图片的方法贴出来):
/// <summary> /// 打印图片方法 /// </summary> public void PrintOne() { //获取图片 Bitmap bmp = new Bitmap(pictureBox1.Image); //设置字符行间距为n点行 //byte[] data = new byte[] { 0x1B, 0x33, 0x00 }; string send = "" + (char)(27) + (char)(51) + (char)(0); byte[] data = new byte[send.Length]; for (int i = 0; i < send.Length; i++) { data[i] = (byte)send[i]; } lc.Write(data); data[0] = (byte)'\x00'; data[1] = (byte)'\x00'; data[2] = (byte)'\x00'; // Clear to Zero. Color pixelColor; //ESC * m nL nH d1…dk 选择位图模式 // ESC * m nL nH byte[] escBmp = new byte[] { 0x1B, 0x2A, 0x00, 0x00, 0x00 }; escBmp[2] = (byte)'\x21'; //nL, nH escBmp[3] = (byte)(bmp.Width % 256); escBmp[4] = (byte)(bmp.Width / 256); //循环图片像素打印图片 //循环高 for (int i = 0; i < (bmp.Height / 24 + 1); i++) { //设置模式为位图模式 lc.Write(escBmp); //循环宽 for (int j = 0; j < bmp.Width; j++) { for (int k = 0; k < 24; k++) { if (((i * 24) + k) < bmp.Height) // if within the BMP size { pixelColor = bmp.GetPixel(j, (i * 24) + k); if (pixelColor.R == 0) { data[k / 8] += (byte)(128 >> (k % 8)); } } } //一次写入一个data,24个像素 lc.Write(data); data[0] = (byte)'\x00'; data[1] = (byte)'\x00'; data[2] = (byte)'\x00'; // Clear to Zero. } //换行,打印第二行 byte[] data2 = { 0xA }; lc.Write(data2); } // data lc.Write("\n\n"); }
在打印过程中,出现一个比较低级的错误,因为小票打印机是并口的,而我电脑是串口的,所以一直远程在另一台电脑上测试,所以打印出来的图片中间多了一条横线,这个问题解决了多半天,因为我一直考虑到是打印图片中可能少一层循环的问题,所以顺便把打印图片的原理整理了一下(之前的循环是从网上找到的,感觉应该没问题就没有细研究)。下面分享一下我的理解:
这是打印位图的命令(每一个打印机都会给出这样的说明,可以直接下载到的):
1. ESC* m nL nH d1…dk 选择位图模式
格式: ASCII: ESC * m nL nH d1…dk
十进制: [27] [42] m nL nH d1…dk
十六进制: [1BH][2AH] m nL nH d1…dk
说明:
.设定位图方式(用m)、点数(用nL,nH)以及位图内容(用dk)。
.m=0,1,32,33;0≤nL≤255,0≤nH≤3,0≤d≤255。
k=nL+nH×256(m=0,1);k=(nL+nH×256)×3(m=32,33)。
.水平方向点数为(nL+nH×256)。
.如果点数超过一行,超过其最大点数(与选择的位图方式有关,详 见下表)的部分被忽略。
.d为位图数据字节,对应位为1则表示该点打印,对应位为0,则 表示该点不打印。(k表示数据个数)
.m用于选择位图方式。
m |
模式 |
纵向 |
横向 |
||
点数 |
分辨率 |
分辨率 |
数据个数(k) |
||
0 |
8点单密度 |
8 |
67 DPI |
100 DPI |
nL+nH×256 |
1 |
8点双密度 |
8 |
67 DPI |
200 DPI |
nL+nH×256 |
32 |
24点单密度 |
24 |
200 DPI |
100 DPI |
(nL+nH×256)×3 |
33 |
24点双密度 |
24 |
200 DPI |
200 DPI |
(nL+nH×256)×3 |
这次用的打印机打印是24点双密度的,所以我这里就只解释下m=33的情况。
从代码中可以看出,打印图片过程主要是通过循环一点点打印的,通过
lc.Write(data);
循环写入,当然前面的lc.Write(escBmp)主要是些ESC * m三个参数很容易理解就不多解释了。而data是一个长度为3的byte数组,这个data在打印中起到什么作用呢?
在打印机m=33的模式纵向每次是打印24个点,也就是说,而byte为8个字节,所以需要3个byte类型的树才能完成模式为24点双密码的位图打印方式,通过三个字符来平凑一个像素宽24个像素长的图片,然后循环宽度,来打印图片宽度大小24个像素高度的图片,在通过每次循环24个像素的高度,最终打印出完成的图片。
需要打印的图片:
第一次循环先是高位24像素
然后把宽度分解开,循环每一像素的宽度,然后打印每一像素宽度的图片:
举个例子,假设数组data[d1,d2,d3],d1= 00000111,d2=11111111,d3 =11111111,所以打印出的一个像素宽,24像素高的图片为:
最终通过循环宽度与高度,把最终的位图画出来。
这里我举的是24点密度的例子,通过,如果您有兴趣研究的话,也经常看到这样的代码:
for (int i = 0; i < ((bmp.Height + 7) / 8); i++) { _serialPort.Write(escBmp, 0, escBmp.Length); for (int j = 0; j < bmp.Width; j++) { for (int k = 0; k < 8; k++) { if (((i * 8) + k) < bmp.Height) // if within the BMP size { pixelColor = bmp.GetPixel(j, (i * 8) + k); if (pixelColor.R == 0) { data[0] += (byte)(128 >> k); } } } _serialPort.Write(data, 0, 1); data[0] = (byte)'\x00'; // Clear to Zero. }
这个很明显就是8点密度的模式,所以他的data长度为1,即需要8个字节就够了。
打印出的效果还是很不错的。
如果大家有兴趣研究网络打印,请参加小崔的博客:http://blog.csdn.net/xiaoxian8023/article/details/8440625#comments
转载于:https://www.cnblogs.com/randyzhuwei/p/5216413.html
C# 热敏打印机 小票打印机 打印图片相关推荐
- delphi android 打印机,用delphi控制小票打印机打印图片
用delphi控制小票打印机打印图片 unit PosPrintBmp; {************************************************************** ...
- 转:C#并口热敏小票打印机打印位图
最近一直在研究并口小票打印机打印图片问题,这也是第一次和硬件打交道,不过还好,最终成功了. 这是DEMO的窗体: 下面是打印所需要调用的代码: [html] view plain copy class ...
- C#并口热敏小票打印机打印位图
C#并口热敏小票打印机打印位图 原文:C#并口热敏小票打印机打印位图 最近一直在研究并口小票打印机打印图片问题,这也是第一次和硬件打交道,不过还好,最终成功了. 这是DEMO的窗体: 下面是打印所需要 ...
- 常见小票打印机打印故障及解决方法汇总视频教程
通过对"常见小票打印机故障及解决方法汇总视频教程"课程学习,达到以下目的:1.可以独立自主安装打印机驱动以及安装打印机硬件设备 2.可以独立自主排除常见打印机故障 学习教程 常见小 ...
- Android 实现系统打印机打印图片,文本,以及二维码生成与解析
打码机:扫码,生成打印自定义标签 一.Android 打印机要支持,网络.WiFi :手机与打印机在同一网络下才行,本文用WiFi连接 打开系统打印服务: 设置--更多设置--打印--选择默认打印 ...
- python打印机打印图片_python连接打印机实现打印文档、图片、pdf文件等功能
引言 python连接打印机进行打印,可能根据需求的不同,使用不同的函数模块. 如果你只是简单的想打印文档,比如office文档,你可以使用ShellExecute方法,对于微软office的文档.p ...
- 打印机打印图片文字有重影
打印机打印图片出来的文字有重影 解决办法: 打印机属性里面"纸张/质量"选项里"颜色"选项选择黑白,不过打印有彩色有黑字的照片还是个问题
- 常见小票打印机打印故障及解决方法汇总视频教程-王西猛-专题视频课程
常见小票打印机打印故障及解决方法汇总视频教程-548人已学习 课程介绍 通过对"常见小票打印机故障及解决方法汇总视频教程"课程学习,达到以下目的:1.可以独立自主安 ...
- 微信小程序连接蓝牙打印机打印图片示例
微信小程序连接蓝牙打印机示例 完整的代码示例请点击看github 小程序连接蓝牙打印机打印文本与二维码等示例在 github 上都能找到一些,唯独打印图片这个案例几乎没有.希望能帮助到有打印图片需求的 ...
最新文章
- 简单了解Vue的自定义组件与生命周期
- .Net Core使用Ocelot网关(二) -鉴权认证
- 查看windows所有exe的启动参数。
- 【图像压缩】基于matlab JEPG图像压缩【含Matlab源码 1167期】
- 稳压管(齐纳二极管)封装型号大全
- 网维无盘服务器错误代码,网维大师无盘环境INTER傲腾方案常见问题解答?
- dqw3721:自己动手写打印机监控程序
- cosx的麦克劳林级数是多少_余弦函数的泰勒级数
- Win10家庭版安装软件时提示“为了对电脑进行保护,已经阻止此应用”
- 正则表达式 /^[0-9]+$/
- SNS背后的科学(1)从六度分隔到无尺度网络
- 智能穿戴:致我们触手可及的未来?
- 在OTFS学习中的一些总结
- PTA-L1-007 念数字 (C语言)
- [Splay的应用]
- [新人向]MySQL和Navicat下载、安装及使用详细教程
- 转:数据可视化之美:经典案例与实践解析
- 2022年,反思你的 HRIS 是不是为绩效管理而构建
- 计算机班教室布置,教室布置班级简介
- html语言中行距如何设定,html怎么设置行间距离