最近一直在研究并口小票打印机打印图片问题,这也是第一次和硬件打交道,不过还好,最终成功了。

这是DEMO的窗体:

下面是打印所需要调用的代码:

[html] view plain copy
  1. class LptControl
  2. {
  3. private string LptStr = "lpt1";
  4. public LptControl(string l_LPT_Str)
  5. {
  6. LptStr = l_LPT_Str;
  7. }
  8. [StructLayout(LayoutKind.Sequential)]
  9. private struct OVERLAPPED
  10. {
  11. int Internal;
  12. int InternalHigh;
  13. int Offset;
  14. int OffSetHigh;
  15. int hEvent;
  16. }
  17. //调用DLL.
  18. [DllImport("kernel32.dll")]
  19. private static extern int CreateFile(string lpFileName, uint dwDesiredAccess, int dwShareMode, int lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, int hTemplateFile);
  20. [DllImport("kernel32.dll")]
  21. private static extern bool WriteFile(int hFile, byte[] lpBuffer, int nNumberOfBytesToWrite, ref int lpNumberOfBytesWritten, ref OVERLAPPED lpOverlapped);
  22. [DllImport("kernel32.dll")]
  23. private static extern bool CloseHandle(int hObject);
  24. private int iHandle;
  25. /// <summary>
  26. /// 打开端口
  27. /// </summary>
  28. /// <returns></returns>
  29. public bool Open()
  30. {
  31. iHandle = CreateFile(LptStr, 0x40000000, 0, 0, 3, 0, 0);
  32. // iHandle = CreateFile(LptStr, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
  33. if (iHandle != -1)
  34. {
  35. return true;
  36. }
  37. else
  38. {
  39. return false;
  40. }
  41. }
  42. /// <summary>
  43. /// 打印字符串,通过调用该方法可以打印需要的字符串
  44. /// </summary>
  45. /// <param name="Mystring"></param>
  46. /// <returns></returns>
  47. public bool Write(String Mystring)
  48. {
  49. //如果端口为打开,则提示,打开,则打印
  50. if (iHandle != -1)
  51. {
  52. OVERLAPPED x = new OVERLAPPED();
  53. int i = 0;
  54. //byte[] mybyte = System.Text.Encoding.Default.GetBytes(Mystring);
  55. byte[] mybyte = Encoding.GetEncoding("GB2312").GetBytes(Mystring);
  56. bool b = WriteFile(iHandle, mybyte, mybyte.Length, ref i, ref x);
  57. return b;
  58. }
  59. else
  60. {
  61. throw new Exception("不能连接到打印机!");
  62. }
  63. }
  64. /// <summary>
  65. /// 打印命令,通过参数,可以打印小票打印机的一些命令,比如换行,行间距,打印位图等。
  66. /// </summary>
  67. /// <param name="mybyte"></param>
  68. /// <returns></returns>
  69. public bool Write(byte[] mybyte)
  70. {
  71. //如果端口为打开,则提示,打开,则打印
  72. if (iHandle != -1)
  73. {
  74. OVERLAPPED x = new OVERLAPPED();
  75. int i = 0;
  76. return WriteFile(iHandle, mybyte, mybyte.Length, ref i, ref x);
  77. }
  78. else
  79. {
  80. throw new Exception("不能连接到打印机!");
  81. }
  82. }
  83. /// <summary>
  84. /// 关闭端口
  85. /// </summary>
  86. /// <returns></returns>
  87. public bool Close()
  88. {
  89. return CloseHandle(iHandle);
  90. }
  91. }

因为我们这里主要是打印条形码和二维码,所以以条形码和二维码为例,写了一个小的调用程序(这里把打印图片的方法贴出来):

[html] view plain copy
  1. /// <summary>
  2. /// 打印图片方法
  3. /// </summary>
  4. public void PrintOne()
  5. {
  6. //获取图片
  7. Bitmap bmp = new Bitmap(pictureBox1.Image);
  8. //设置字符行间距为n点行
  9. //byte[] data = new byte[] { 0x1B, 0x33, 0x00 };
  10. string send = "" + (char)(27) + (char)(51) + (char)(0);
  11. byte[] data = new byte[send.Length];
  12. for (int i = 0; i < send.Length; i++)
  13. {
  14. data[i] = (byte)send[i];
  15. }
  16. lc.Write(data);
  17. data[0] = (byte)'\x00';
  18. data[1] = (byte)'\x00';
  19. data[2] = (byte)'\x00';    // Clear to Zero.
  20. Color pixelColor;
  21. //ESC * m nL nH d1…dk   选择位图模式
  22. // ESC * m nL nH
  23. byte[] escBmp = new byte[] { 0x1B, 0x2A, 0x00, 0x00, 0x00 };
  24. escBmp[2] = (byte)'\x21';
  25. //nL, nH
  26. escBmp[3] = (byte)(bmp.Width % 256);
  27. escBmp[4] = (byte)(bmp.Width / 256);
  28. //循环图片像素打印图片
  29. //循环高
  30. for (int i = 0; i < (bmp.Height / 24 + 1); i++)
  31. {
  32. //设置模式为位图模式
  33. lc.Write(escBmp);
  34. //循环宽
  35. for (int j = 0; j < bmp.Width; j++)
  36. {
  37. for (int k = 0; k < 24; k++)
  38. {
  39. if (((i * 24) + k) < bmp.Height)  // if within the BMP size
  40. {
  41. pixelColor = bmp.GetPixel(j, (i * 24) + k);
  42. if (pixelColor.R == 0)
  43. {
  44. data[k / 8] += (byte)(128 >> (k % 8));
  45. }
  46. }
  47. }
  48. //一次写入一个data,24个像素
  49. lc.Write(data);
  50. data[0] = (byte)'\x00';
  51. data[1] = (byte)'\x00';
  52. data[2] = (byte)'\x00';    // Clear to Zero.
  53. }
  54. //换行,打印第二行
  55. byte[] data2 = { 0xA };
  56. lc.Write(data2);
  57. } // data
  58. lc.Write("\n\n");
  59. }

在打印过程中,出现一个比较低级的错误,因为小票打印机是并口的,而我电脑是串口的, 所以一直远程在另一台电脑上测试,所以打印出来的图片中间多了一条横线,这个问题解决了多半天,因为我一直考虑到是打印图片中可能少一层循环的问题,所以 顺便把打印图片的原理整理了一下(之前的循环是从网上找到的,感觉应该没问题就没有细研究)。下面分享一下我的理解:

这是打印位图的命令(每一个打印机都会给出这样的说明,可以直接下载到的):

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用于选择位图方式。

模式

纵向

横向

点数

分辨率

分辨率

数据个数(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点密度的例子,通过,如果您有兴趣研究的话,也经常看到这样的代码:

[html] view plain copy
  1. for (int i = 0; i < ((bmp.Height + 7) / 8); i++)
  2. {
  3. _serialPort.Write(escBmp, 0, escBmp.Length);
  4. for (int j = 0; j < bmp.Width; j++)
  5. {
  6. for (int k = 0; k < 8; k++)
  7. {
  8. if (((i * 8) + k) < bmp.Height)  // if within the BMP size
  9. {
  10. pixelColor = bmp.GetPixel(j, (i * 8) + k);
  11. if (pixelColor.R == 0)
  12. {
  13. data[0] += (byte)(128 >> k);
  14. }
  15. }
  16. }
  17. _serialPort.Write(data, 0, 1);
  18. data[0] = (byte)'\x00'; // Clear to Zero.
  19. }

这个很明显就是8点密度的模式,所以他的data长度为1,即需要8个字节就够了。

打印出的效果还是很不错的。

如果大家有兴趣研究网络打印,请参加小崔的博客:http://blog.csdn.net/xiaoxian8023/article/details/8440625#comments

转载于:https://www.cnblogs.com/dancheblog/p/4535032.html

转:C#并口热敏小票打印机打印位图相关推荐

  1. C#并口热敏小票打印机打印位图

    C#并口热敏小票打印机打印位图 原文:C#并口热敏小票打印机打印位图 最近一直在研究并口小票打印机打印图片问题,这也是第一次和硬件打交道,不过还好,最终成功了. 这是DEMO的窗体: 下面是打印所需要 ...

  2. H5网页调用58热敏小票打印机实现打印小票

    在微信公众号和H5网页开发中,常常需要开发调用打印机进行小票打印操作,通常的做法是调用蓝牙打印机,但是蓝牙打印机由于蓝牙连接的原因,往往稳定性差,需要客户端配合才能发挥好的效果,另外蓝牙打印机距离受限 ...

  3. python调用小票打印机_PyQt5中使用Qprinter打印热敏小票

    在<PyQt5中使用QWebChannel和内嵌网页进行js交互>一文中,我记录了如何使用QWebchannel与内嵌网页进行js交互,其根本目标在于使用Qt5调起打印机服务.在这篇文章中 ...

  4. 为什么从网页上打印怎们好像被缩放_便捷高效低成本,映美热敏云打印机CTP-180UWE体验...

    打印机的分好几种,喷墨.激光.针式.热敏,还有之前火过一阵子的3D打印机等,前面三种我们公司都有在用,我同事打印单据都喜欢用针式,因为激光打印机出来的都是A4,太大了,也浪费.但是针式打印机速度很慢, ...

  5. java热敏POS打印机编程

    今天有时间,就整理一下关于java控制热敏POS打印机的一些注意事项,不然怕以后会忘记. 所谓热敏POS打印机,就是小超市的小票打印机.对于此打印机,我也只是半懂而已,如以下说的不对的地方,还请指正. ...

  6. python打印小票_PyQt5中使用Qprinter打印热敏小票

    在<PyQt5中使用QWebChannel和内嵌网页进行js交互>一文中,我记录了如何使用QWebchannel与内嵌网页进行js交互,其根本目标在于使用Qt5调起打印机服务.在这篇文章中 ...

  7. 如何使用E邮宝的热敏标签纸打印亚马逊外箱单?

    普通的热敏打印机可以打印亚马逊FBA标签和外箱标签吗? 如何使用条码打印机打印亚马逊FBA外箱标签? 亚马逊的外箱标签可以用热敏打印吗? FBA外箱标签怎么打印? 如打印何亚马逊发货标签? FBA发货 ...

  8. C# 热敏打印机 小票打印机 打印图片

    最近一直在研究并口小票打印机打印图片问题,这也是第一次和硬件打交道,不过还好,最终成功了. 这是DEMO的窗体: 下面是打印所需要调用的代码: class LptControl { private s ...

  9. delphi android 打印机,用delphi控制小票打印机打印图片

    用delphi控制小票打印机打印图片 unit PosPrintBmp; {************************************************************** ...

最新文章

  1. 手撕FSG2.0壳(有坑点)
  2. virtualbox中Centos6.6和windows共享文件夹设置
  3. java 字节序列_java – 这个线程安全的字节序列生成器有什么问题?
  4. YBTOJ洛谷P4074:糖果公园(树上莫队)
  5. nvme固态硬盘开机慢_为何我使用了固态硬盘开机速度还是需要20-30秒
  6. Go实现简单负载均衡
  7. 简述 HTTPS 证书认证
  8. 深度神经网络调参经验
  9. Oracle数据库to_date()和to_char()的相关
  10. 【CF551D】GukiZ and Binary Operations
  11. 【Webcam设计】相机底层工作流程,编程模型
  12. cefsharp远程调试工具
  13. java微信公众号百度地图,微信企业号开发之微信考勤百度地图定位
  14. Java项目经验之交易密码安全机制
  15. 【AI产品】认猫、认花、认车、认吃,请认准识别全能王
  16. 罗技 连点 脚本_双十一,罗技,价格不贵又好用的办公无线鼠标,吐血推荐!2020.10月,双11...
  17. 【STM32F429】第5章 RL-USB移植(MDK AC6)
  18. 代发核心期刊骗局_“代发论文”骗局:近2000人被骗 多数不愿报案
  19. Re-ID: Person Re-identification by Local Maximal Occurrence Representation and Metric Learning 论文解析
  20. java国密 C#国密 golang国密 NodeJS国密汇总(三)

热门文章

  1. JavaScript案例:实现对象的深拷贝
  2. git reset --soft 版本回退多了,怎么恢复?
  3. 测试 | 讯飞星火升级,能力有很大提升,不再一本正经胡说
  4. 算法与数据结构(六) 迪杰斯特拉算法的最短路径(Swift版)
  5. 单链表——单链表逆置(不带头结点)
  6. Grep命令查找多个字符串(grep同时匹配多个关键字或任意关键字)
  7. WIFI模块-ESP8266-ESP-01使用指南
  8. 微软第二代HoloLens重点不在硬件 而在云服务
  9. OpenText 企业内容管理平台客户案例——印度鲁宾(Lupin)制药公司
  10. nagios 安装问题解析