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 nHbyte[] escBmp = new byte[] { 0x1B, 0x2A, 0x00, 0x00, 0x00 };escBmp[2] = (byte)'\x21';//nL, nHescBmp[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);} // datalc.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/lonelyxmas/p/9282391.html
C#并口热敏小票打印机打印位图相关推荐
- 转:C#并口热敏小票打印机打印位图
最近一直在研究并口小票打印机打印图片问题,这也是第一次和硬件打交道,不过还好,最终成功了. 这是DEMO的窗体: 下面是打印所需要调用的代码: [html] view plain copy class ...
- H5网页调用58热敏小票打印机实现打印小票
在微信公众号和H5网页开发中,常常需要开发调用打印机进行小票打印操作,通常的做法是调用蓝牙打印机,但是蓝牙打印机由于蓝牙连接的原因,往往稳定性差,需要客户端配合才能发挥好的效果,另外蓝牙打印机距离受限 ...
- python调用小票打印机_PyQt5中使用Qprinter打印热敏小票
在<PyQt5中使用QWebChannel和内嵌网页进行js交互>一文中,我记录了如何使用QWebchannel与内嵌网页进行js交互,其根本目标在于使用Qt5调起打印机服务.在这篇文章中 ...
- 为什么从网页上打印怎们好像被缩放_便捷高效低成本,映美热敏云打印机CTP-180UWE体验...
打印机的分好几种,喷墨.激光.针式.热敏,还有之前火过一阵子的3D打印机等,前面三种我们公司都有在用,我同事打印单据都喜欢用针式,因为激光打印机出来的都是A4,太大了,也浪费.但是针式打印机速度很慢, ...
- python打印小票_PyQt5中使用Qprinter打印热敏小票
在<PyQt5中使用QWebChannel和内嵌网页进行js交互>一文中,我记录了如何使用QWebchannel与内嵌网页进行js交互,其根本目标在于使用Qt5调起打印机服务.在这篇文章中 ...
- java热敏POS打印机编程
今天有时间,就整理一下关于java控制热敏POS打印机的一些注意事项,不然怕以后会忘记. 所谓热敏POS打印机,就是小超市的小票打印机.对于此打印机,我也只是半懂而已,如以下说的不对的地方,还请指正. ...
- 如何使用E邮宝的热敏标签纸打印亚马逊外箱单?
普通的热敏打印机可以打印亚马逊FBA标签和外箱标签吗? 如何使用条码打印机打印亚马逊FBA外箱标签? 亚马逊的外箱标签可以用热敏打印吗? FBA外箱标签怎么打印? 如打印何亚马逊发货标签? FBA发货 ...
- C# 热敏打印机 小票打印机 打印图片
最近一直在研究并口小票打印机打印图片问题,这也是第一次和硬件打交道,不过还好,最终成功了. 这是DEMO的窗体: 下面是打印所需要调用的代码: class LptControl { private s ...
- delphi android 打印机,用delphi控制小票打印机打印图片
用delphi控制小票打印机打印图片 unit PosPrintBmp; {************************************************************** ...
最新文章
- 读 MySQL 源码再看 INSERT 加锁流程
- 在Powerpoint中插入Flash的方法
- 课堂测试-找英语单词最长链
- 基于FPGA的costas环同步系统仿真与分析
- Crawler之Scrapy:数据挖掘必备的scrapy框架之最完整爬取网页内容攻略
- ValueError: No engine for filetype: 'csv'解决与书本7-2代码改写
- oracle 如何筛选重复,求sql--筛选A字段相同,B字段不同且不重复的记录
- 秒懂物理计算机出题规划,57张动图, 让你秒懂高中物理原理! 考试次次拿第一
- Android系统搜索对话框(浮动搜索框)的使用
- 用Vue.js和Webpack开发Web在线钢琴
- 程序员转行杀猪是种什么体验?
- VMware Vsphere 虚拟化
- idea无法下载源码 Sources not found for: org.springframework:spring-context:5.1.5.RELEAS
- cv2批量修改图片大小
- 《万字长文》-吃透Docker-进阶篇
- CUDA C编程(五)并行性的表现以及避免分支分化
- Android Q USB Tethering 端口切换分析
- 24 个很酷的 Linux/Unix 工具
- osg 根据两个点的经纬度计算方位角
- jsp四大作用域和九大对象
热门文章
- 2023最新仿小鸟云主机服务器IDC网站源码+支持WAP响应式
- ajp 定向包协议 二进制代替文本提高性能 简介
- MATLAB拟合曲线绘制
- SNAT与DNAT原理与应用
- 关闭msmpeng_关闭 MsMpEng.exe
- 从零开始 荔枝派nano TF卡启动
- Nature reviews neuroscience:后扣带皮层的三分观点
- tcpdump 详细使用指南(请尽情食用)
- JavaSE基础学习——内部类
- 【医学+深度论文:F23】2018 symmetry Dense Fully Convolutional Segmentation of the Optic Disc and