指令打印与驱动打印随笔

本文对指令打印和驱动打印做了一个简要的介绍,分享了在开发客户端打印组件时的一些过程并提出了一个新轮子用于解决老的问题并引出更多的新问题。全文大概 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 这三个条件。但设计一种高级指令并不是唯一需要的事情,仍有许多工作要做比如这种高级指令的解析和转换等。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/312434.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

er图转为数据流程图_「数据架构」实体关系模型介绍

实体-关系模型(或ER模型)描述特定知识领域中相关的事物。基本的ER模型由实体类型(对感兴趣的事物进行分类)和指定实体之间可能存在的关系(那些实体类型的实例)组成。在软件工程中,为了执行业务流程,ER模型通常用于表示业务需要记住的内容。因此&#xff…

WeihanLi.Npoi 1.7.0 更新介绍

WeihanLi.Npoi 1.7.0 更新介绍Intro昨天晚上发布了 WeihanLi.Npoi 1.7.0 版本,增加了 ColumnInputFormatter/ ColumnOutputFormatter,又进一步增强了导入导出的灵活性,来看下面的示例ColumnInputFormatter/ColumnOutputFormatter示例 Model:i…

【复杂系统迁移 .NET Core平台系列】之迁移项目工程

源宝导读:微软跨平台技术框架—.NET Core已经日趋成熟,已经具备了支撑大型系统稳定运行的条件。本文将介绍明源云ERP平台从.NET Framework向.NET Core迁移过程中的实践经验。一、背景随着ERP的产品线越来越多,业务关联也日益复杂,…

分析股票大数据_Python大数据分析量学祖师爷网站数据

本文通过Python抓取股海明灯涨停预报数据进行分析,股海明灯网站涨停预报数据跟踪功能是需要VIP权限,但这个权限分析数据的功能有限,我们抓取数据后丰富相关功能。一、点击涨停预报后打开以下页面。通过python程序将数据抓取到后台数据库&…

【复杂系统迁移 .NET Core平台系列】之界面层

源宝导读:微软跨平台技术框架—.NET Core已经日趋成熟,已经具备了支撑大型系统稳定运行的条件。本文将介绍明源云ERP平台从.NET Framework向.NET Core迁移过程中的实践经验。一、背景随着ERP的产品线越来越多,业务关联也日益复杂,…

.NET Core MVC扩展实践

源宝导读:明源云ERP的底层架构正在向.Net Core跨平台迁移,我们在过程中遇到了部分不兼容的问题。本文将介绍技术团队如何解决.Net Core与已有MVC框架不兼容问题的解决方案。一、背景云ERP的建模平台是基于.NET Framework构建的,在向.NET Core…

matlab title多个标题_MATLAB中的直方图处理及均衡化

直方图是多种空间域处理技术的基础。仿图操作能有效地用于图像增强,直方图固有的信息在其他图像处理应用中也是非常有用的,如图像压缩与分割。訪图在软件中易于计算,也适用于商用硬件设备,因此直方图成为实时图像处理的一个流行工…

成本计算引擎动态规则解析技术详解

源宝导读:随着企业数字系统应用的越来越深入,业务计算方式也变的越来越复杂,灵活度要求也越来越高。本文将介绍通过将配置动态转换成可执行代码的方式,解决业务计算高度灵活化配置的技术方案。一、背景ERP本质上是一种“业务密集型…

Kubernetes,多云和低代码数据科学:2020年最热门的数据管理趋势

新兴技术为我们的数据之旅铺平了道路。我们已经看到Kubernetes在应用程序自动化方面处于领先地位,越来越多的公司将赌注押在了云上,以及当今的企业对数据科学的依赖程度正不断提,再加上对大数据的人工智能高级分析,可以看到数据管…

matlab光盘映像文件可以删除吗_DVD-Cloner 2020 for mac(DVD光盘刻录工具) 7.00.715

DVD-Cloner Gold 2020版是功能强大的DVD光盘刻录工具,DVD-Cloner Gold 2020版可以轻松刻录光盘以及蓝光光盘,用户可以将任何的文件刻录到DVD光盘中,并可以制作为蓝光光盘,可以很方便地录入视频到光盘中进行保存,刻录好…

性能优化 = 改改代码?

大家好,我是Z哥。好久没写技术文章了,最近正好有进行一些思考,顺手写出来分享给大家。如果不是程序员的话,可以快速扫一眼正文的几个小标题,快速略过即可,毕竟思路和专业无关,很多是相通的。&am…

使用refs获取节点_闲庭信步聊前端 - 原来你是这样的Refs

一、refs 的由来什么是refsrefs是拿到真实的DOM节点和React元素实例的一种方法。在React官方文档中有提到Refs 提供了一种方式,允许我们访问 DOM 节点或在 render 方法中创建的 React 元素。 React是单向的数据流,父子组件的交互是通过props。修改子组件…

从TimeSpan说起

小编在编写WPF程序时,需要做一个判断:定时使用Modbus协议使用Quartz.net 定时任务读取设备中的数据,同时也使用定时任务判断是否长时间获取不到数据的情况,如果程序中超过一分钟没有获取到数据(数据没有更新&#xff0…

如何维持手机电池寿命_延长手机电池寿命终极技巧教学,iPhone和安卓手机皆适合...

每隔一阵子就开始有不少用户询问,iPhone电池健康度又剩下多少了,怎么朋友的还维持在100%,是不是我手机电池出问题,引起不少用户翻白眼。会有电池健康度,最主要是要让大家了解目前手机电池当前寿命,只要电池…

2020年了,再不会Https就老了

合格的web后端程序员,除搬砖技能,还必须会给各种web服务器启用Https,本文结合ASP.NET Core部署模型聊一聊启用Https的方式。温故知新目前常见的Http请求明文传输,请求可能被篡改,访问的站点可能被伪造。HTTPS是HTTP加上…

c语言枚举类型例题_[开源资讯]Zig 0.6.0 发布,想要挑战 C 语言

Zig 0.6.0 已发布,这是一门通用编程语言,专为稳定性、可维护性和性能而设计,追求替代 C 语言在系统编程上的最佳地位。Zig 具有以下值得关注的特性:手动管理内存与 C 语言竞争而非依赖它,Zig 标准库不依赖于 libc轻量而…

【实战 Ids4】║ 给授权服务器加个锁——HTTPS配置

在上篇文章《【实战 Ids4】║客户端、服务端、授权中心全线打通!》中,我们正式的将三站打通,发布过后,有小伙伴反馈,可能Nginx对配置HTTPS安全协议有点儿问题,我也就半夜趁着没人打扰,疯狂的研究…

快速幂 a*b%c

2020.12.30开始学习AcWing算法《算法竞赛进阶指南》&#xff1b; 在CSDN上传博客方便复习。 //wecccccccc //2020.12.30 #include <iostream> using namespace std; typedef long long int ll;ll fast_power(ll a, ll b, ll c) {ll ans 1;a % c;//防止一开始输入的值过…

thinkphp 助手函数url不生成https_如何用ThinkPHP框架写一个快递查询接口

ThinkPHP是php程序员们经常使用的框架之一&#xff0c;运用框架来开发网站无疑减轻了我们代码量&#xff0c;加快了我们的开发速度&#xff0c;框架底层封装的方法和函数使用起来简直不能太爽。今天给大家总结一个小案例&#xff0c;如何实现一个快递查询的接口。所谓接口&…

64位整数乘法

2020.12.30开始学习AcWing算法《算法竞赛进阶指南》&#xff1b; 上传博客方便复习。 //Wecccccccc //2020.12.30 #include <iostream> using namespace std; typedef unsigned long long int ull;int main() {ull a, b, c;cin >> a >> b >> c;ull ans…