本文对指令打印和驱动打印做了一个简要的介绍,分享了在开发客户端打印组件时的一些过程并提出了一个新轮子用于解决老的问题并引出更多的新问题。全文大概 3500 字无图,阅读大概需要 7 分钟。

驱动打印是指:使用 PrintDocument 进行打印。通过注册其 PrintPage 方法拿到 Graphics 对象使用 GDI+ 画图打印。

指令打印是指:利用打印机厂商提供的指令协议控制打印机直接打印。

驱动打印和 Windows 平台关联紧密,所以不能做到跨平台。驱动打印大部分情况不能即插即用,在第一次将某打印机链接到电脑时,可能需要安装对应的驱动程序系统才能正确的识别到该打印机。

绝大部分小票打印机都支持 ESC 指令,除了 ESC 外常见的还有 TSC、TSPL,PPLA等这与打印机厂商和型号相关。指令打印可以跨平台,且在不同的平台要向硬件发出的指令是相同的,无论链接方式是 USB、串口还是蓝牙。

从开发的角度来说,如果我们想兼容市面上大多数打印机并且想支持跨平台,那么这就会是一件需要仔细斟酌和权衡的事情:

1、仅采用驱动打印。那么我们不得不放弃对跨平台的支持。如果遇到过老的设备,它很可能没有提供对最新的操作系统(比如 Windows 10)的支持,所以单纯的驱动打印是玩儿不赢的。

2、仅采用指令打印。我们可以做到跨平台,无惧系统升级,但仍有无解的情况:如果客户的打印机没有指令打印或者指令协议很小众没必要做支持怎么办?这是真实发生的事情,有客户需要用传统的办公用打印机打印小票,真·谜一般的操作。

3、驱动打印和指令打印并行。这当然会解决上述问题,但同时会引入新的问题:你不得不写出多套不同的代码去完成一件相同的事情,更可怕的是在修改一个问题时很可能会改了这一套忘了那一套。

在项目起初,因为对各种打印方案并不熟悉所以带你部分经过了上述三个阶段的演变。当支持的打印机和打印格式越来越多,维护这部分代码就成为一件苦力活儿,而且非常容易出错。接手这部分代码的人会被怀疑是否能力有问题,毕竟开始的时候时那么的简单。

大概 2019 年 7 月份时,项目组对驱动打印进行了封装,该封装参考了网上的开源组件,构建出了一个名为 TicketDocument 的类型,并添加了一些基础操作:

TicketDocument 可以序列化为 JSON 字符串用于在网络间传输。所以可以将 TicketDocument 的生成放置在服务端,这样对打印格式进行微调时不需要更新客户端。

项目中对 TicketDocument 的调用类似如下,其中 doc 变量即 TicketDocument 实例:

doc.AddText($"来源:{g.SName}");
doc.AddNewRow();
doc.AddText($"出厂时间:{g.CommandDate:yyyy/MM/dd}");
doc.AddNewRow();
doc.AddText($"产品:{g.Items.Count(i => i.FXashId == 0)}件", width: 0.4f);
doc.AddText($"附件:{g.Items.Count(i => i.FXashId != 0)}件", width: 0.3f, offset: 0.4f,
alignment: StringAlignment.Center);
doc.AddText($"共计:{g.Items.Count}件", width: 0.3f, offset: 0.7f, alignment: StringAlignment.Far);

当项目不得不支持指令打印时, TicketDocument 的抽象定义就不能满足需求了:因为指令打印并不能提供类似于 GDI+ 这种强大的控制力。

驱动打印和指令打印并行的事情必须上马。因为指令各不相同,所以就编写了不同的代码对应不同的打印机,业务应用调用打印宿主时也采用多种不同的协议格式,因项目不同没有使用 TicketDocument 。这对驱动打印部分造成了影响,满天飞的硬编码,写死的数组下标,接着在对打印格式进行调整时,驱动打印罢工了。

于是,我们需要一个新的轮子:

  1. 它应该满足跨平台打印的需求,在 Windows、Android、iOS 中有相同的行为表现。

  2. 它应该同时支持驱动打印和指令打印。

  3. 在满足前两条的同时,它应该尽量减少新增格式时的工作量。

All problems in computer science can be solved by another level of indirection .

计算机科学中的所有问题都可以通过间接的另一个层次来解决。

出自:David Wheeler

这是软件工程学中的一个真理,我们可以引入一种新的自定义指令来决绝上述的问题:

  1. 这种指令是一种高级指令,它对驱动打印和大部分目前受支持的指令打印行为进行了封装。

  2. 这种高级指令最终会被翻译成对 Graphics 的操作或打印机指令。

  3. 这种高级指令由业务系统生成并可以在网络中进行传播。

  4. 这种高级指令可以使用目前的主流编程语言生成,比如 C#、Java、Python、PHP、JavaScript 等。

  5. 这种高级指令应该易于识别,并尽量减少在网络传输中的流量消耗。

TicketDocument 似乎是一个不错的先驱者,目前为止它满足了 3、4、5 这三个条件。但设计一种高级指令并不是唯一需要的事情,仍有许多工作要做比如这种高级指令的解析和转换等。

目前为止我并没有完成对这个轮子的全部设计,以上是对这个轮子的设想。这个轮子在设计上还不完整,有许多空白的部分需要填上。如果您对这个轮子感兴趣,可以收藏本站,在文章下留言或打赏作者,谢谢支持!

指令打印与驱动打印随笔相关推荐

  1. 单片机 驱动 标签打印机tsc_指令打印与驱动打印随笔

    本文对指令打印和驱动打印做了一个简要的介绍,分享了在开发客户端打印组件时的一些过程并提出了一个新轮子用于解决老的问题并引出更多的新问题.全文大概 3500 字无图,阅读大概需要 7 分钟. 驱动打印是 ...

  2. Windows打印体系结构之打印驱动框架

    庐山烟雨浙江潮,未到千般恨不消.到得原来无别事,庐山烟雨浙江潮. 1.2.Windows打印驱动框架 Windows的打印驱动从总体架构上来说,包括一个渲染组件和一个配置组件.我们可以回想一下最开始的 ...

  3. java usb 无驱打印_Windows Usb 无驱动打印

    \?\USB#VID_8866&PID_0100#0001B0000000#{a5dcbf10-6530-11d2-901f-00c04fb951ed} USB小票打印解决办法 一.需要驱动, ...

  4. uniapp调试ESC指令热敏打印机 打印图片 以及 打印途中报10007特性不支持解决方案

    图片需要通过 canvas进行处理 预先在canvas上绘制然后读取图片 打印途中报 10007 特性不支持 解决方案 可以看文章最后的描述 设置图片 chooseImage() {this.clea ...

  5. C++调用win32 API操作打印机实现驱动打印

    方法说明: 1.s2w(string &content, int length):将string类型的变量转换为wchar_t*类型,用于调用TextOut()方法时传参,其中length为需 ...

  6. php esc p 打印,ESC/P 打印指令使用,3种票据打印方法(转)

    具体内容大家自己看!如有好的解决方案大家共同研究! (1)自定义纸张设置 控制面板->打印机和传真->右键->服务器属性->创建新的格式 (2)自定义纸张使用 this.pri ...

  7. UGREEN 绿联 USB 2.0转串口DB9 打印线 驱动安装教程

    UGREEN 绿联 USB 2.0转串口DB9 打印线 驱动安装教程 访问网址https://www.lulian.cn  鼠标停留在 下载/支持 选择USB转串口驱动 三.选中 绿联USB转串口DB ...

  8. 佳能c3320如何u盘打印_佳能c3320驱动|佳能ir adv c3320打印/扫描驱动下载 v21.75 官方版 - 比克尔下载...

    佳能ir adv c3320打印/扫描驱动包含了打印驱动和扫描驱动,是专为佳能ir adv c3320复印机用户打造的,能够解决佳能c3320复印机的一些驱动问题,你只需将复印机电缆断开后安装驱动程序 ...

  9. usb摄像头驱动打印信息

    usb摄像头驱动打印信息 文章目录 usb摄像头驱动打印信息 在ubuntu中接入罗技c920摄像头打印的信息如下: [ 100.873222] usb 3-2: new high-speed USB ...

最新文章

  1. 【错误记录】Flutter 环境安装相关问题 ( 执行 flutter doctor 命令后续错误处理 )
  2. 003_ActiveMQ管理后台
  3. Shell 脚本修改 Mac IP地址
  4. mysql 查看导出数据字典
  5. Android:源码环境编译自定义的APP到ROM(System Image)中
  6. LeetCode 1267. 统计参与通信的服务器(计数)
  7. dagger2 注入_如何使用Dagger 2在您的应用程序中实现依赖注入
  8. 对static静态成员的理解
  9. Vivado debug异常现象
  10. mysql_real_connect阻塞_mysql_real_connect 参数注意-阿里云开发者社区
  11. 函数与导数中常用的函数和不等关系
  12. ubuntu Mac 上ssh保持会话连接
  13. 【浅墨著作】《逐梦旅程:Windows游戏编程之从零开始》勘误配套源代码下载
  14. 设置xshell5编码
  15. Linux清空回收站
  16. CE修改植物大战僵尸-阳光基址(小宇特详解)
  17. MATLAB注意事项
  18. 目标检测-ROI Pooling介绍
  19. 熊孩子乱敲键盘攻破linux桌面,“熊孩子”乱敲键盘就攻破了 Linux 桌面,大神:17 年前我就警告过你们...
  20. CAPEX OPEX

热门文章

  1. 推荐我看过的几本好书给大家!(2)
  2. 文件目录管理与显示c语言,Centos 7 文件和目录管理
  3. 博客暂停通知-------10.1~11.24
  4. 初学者:如何使用虚拟PC将Windows 7安装到虚拟机
  5. Object defineProperty
  6. java启动mysq服务_Java Web开发——MySQL数据库的安装与配置
  7. Safari 版本回退方法
  8. lost connection to MySQL server at waiting for initial communication packet,system error:o
  9. 专题1.1——Exchange2013部署前准备条件
  10. SQL Server默认1433端口修改方法