我从 2017 进入大屏触摸这个行业,主要是做桌面软件这一块。在大屏交互平板这个行业里面的还能看的上去的应用,都是使用 WPF 做的。本文就来和大家聊聊在触摸屏应用开发的时候需要了解的软硬件知识。阅读本文你将能大概了解这个行业的一点知识
触摸屏等于触摸框加屏幕
触摸屏必须要分开看,至少在软件上需要将触摸屏分开为触摸框加屏幕两个模块,因为触摸框会直接影响软件的形态以及逻辑。而屏幕虽然也会影响,但是已经有大量驱动和底层的渲染库解决这部分问题,理论上除非写很底层的开发,否则需要关心的只是屏幕分辨率以及频率,而不需要关心屏幕的显示效果
触摸框提供了触摸输出,而屏幕接收软件的输出。因此一个触摸屏应用拆分为触摸框和屏幕就能拆分两个模块,分别是软件的输入和输出对应的模块
接下来需要告诉大家触摸框有哪些了
触摸框大概可以分为电磁屏、电容屏和红外屏,以及其他屏。我经手最多的是电磁屏、电容屏和红外屏。不同的屏幕对软件的实现逻辑有一定的影响
红外屏
红外屏幕,即红外触摸框,属于成本最低的一个触摸框。基本上市面上的红外触摸框都属于低成本方案。但红外也依然能做到高精度低延时,不过高端红外触摸屏的成本会比同等的电容屏贵一些。当然,这不是绝对的,取决于销售大佬的能力
红外屏的开发需要了解到的是红外是不区分触摸物体的,这个和电磁屏、电容屏相对。红外触摸框的原理是通过光线判断,只要有物体接触屏幕,挡住了光线,就会被触摸框识别到触摸
敲黑板,如果开发的应用会在红外屏上面运行,那么请务必记住上面这句话
注意,任何物体只要挡住了红外触摸框发射的光线,那么将会被识别为触摸
而红外触摸框是通过在屏幕之上添加一个触摸框,因此你可以不必贴合屏幕进行触摸即可被识别为触摸。这个被称为触摸高度。触摸高度指的是距离碰到屏幕的距离有多少就会挡住红外的光线,被识别为触摸
有了触摸高度以及任意物体只要挡住光线即可被识别为触摸,将会给开发带来一些坑
在红外屏开发的时候需要注意屏幕本身是不平的,因此一个屏幕的不同的点的触摸高度可能不同。而如果使用笔之类的三角形大概的物体触摸的时候,此时因为触摸高度不同,因此识别到的触摸面积以及坐标可能不同
因此在红外屏开发的时候,需要注意触摸点需要做很多的补偿,需要做至少一次贝赛尔。如果遇到离群点,需要干掉
默认在 Windows 底层已经做过一次处理了,但是针对于比较便宜的红外触摸框加屏幕做工,需要手动处理离群点的丢掉问题。记住一个参数,在10ms内移动距离不超过xx像素。注意这个 xx 像素是因为软件里面只能知道像素,而不知道物理距离尺寸。因此需要根据具体触摸框和屏幕测试出这个像素值。如果移动距离超出了,请丢这个点
而红外屏会带来的另一个问题是大面积物体触摸问题,假定有一个海绵准备触摸红外屏。在第一刻,你能收到超级多的点离散触摸到屏幕,此时属于多指触摸。而在第二刻你能收到一个比较混乱的值,有一些点的触摸面积变大,而一些点消失或不动,这取决于触摸框供应商的算法。在第三刻就剩下几个点了,同时几个点是存在重叠的
因此在红外屏处理大面积物体触摸的时候,需要做延迟,延迟判断触摸面积到达多大。例如手势擦除功能,不能拿到第一个点获取面积就判断是进行手势擦除或不是手势擦除。注意这里说的手势擦除是一个团队内的术语,听不懂,没关系
而同时需要注意有处理多指触摸的业务的时候,不能在多指触摸立刻响应,需要做延迟,延迟一定的时间如果依然是多指触摸才能进行业务,或者需要设计多指触摸业务可以被打断
因此遇到以下问题的时候,需要想到这是红外屏的特性
- 触摸出现瞬间跳点
- 触摸的时候两个手指距离过近出现黏线,不同角度的黏线距离不同
- 获取到物体的触摸面积在不同的坐标获取到的值不同
- 相同触摸点移动过程中面积变化
- 相同触摸点移动过程中,中心点变化
- 可能存在某个点一直都是被触摸,但找不到这个点的触摸物体
- 触摸移动过快的时候被识别为两段触摸,或者两个不同的手指触摸
红外屏还能有一些好玩的坑,这部分我记录到本文最后的笑话的这一节
电容屏
电容屏会遇到的问题是触摸的时候不一定会响应,同时要求物体几乎完全贴合屏幕才能收到触摸点。为什么触摸的时候不一定会响应,一个原因是触摸的物体的缘故,需要能导电,另外的原因和屏幕的做工相关
电容屏识别物体的面积都是比较准的,但是如果有一个大面积物体触摸的时候,这个物体触摸面不是平整的,意味着可能有部分点能触摸到。而一部分触摸不到,如手背。此时收到的触摸可能是一些离散的点,而不是一个大物体
因此在电容屏上的应用,如果考虑大面积触摸,需要软件添加对相邻触摸点连在一起作为一个新的触摸点的功能
而这部分软件的功能不一定放在应用软件,有一些供应商的触摸框做了这个处理。如果触摸框厂商提供的比较渣,就需要应用软件加上这个逻辑
电容屏的问题是触摸的时候需要差不多完全贴合,而因为屏幕的材料存在摩擦,因此手指滑动的时候会出现瞬间的抬起,因此可能存在瞬间的触摸抬起然后继续触摸
需要软件兼容如果收到抬起之后的 xx ms 再次在抬起的点附近收到按下的点,那么将两个点连接起来。这里的参数需要根据实际的触摸框修改
电磁屏
基本上对应的是电磁笔,这个屏幕因为有电磁笔的存在,因此触摸的坑少了,而笔的坑就多了一些
基本上笔是存在压感的,而默认微软能提供的笔有限。因此做多笔可以尝试使用压感的值分开多个不同的笔。如果你这样做了,后续的坑,相信你也能预料到
而一般的电磁屏和上面两个没有冲突,可以使用电磁屏配合红外屏做到手笔分离的功能。使用电磁笔是写字上报的是Pen协议消息,而使用手触摸走的是红外,上报的是触摸信息
在 WPF 中区别在于笔写字的时候触发的是触笔 Stylus 事件,而触摸的时候则是触发 Touch 以及 Stylus 事件
触摸面积和物理面积
其中触摸面积是一个大坑,尽管标准 HID 协议里面的触摸包含了 X Y 和 宽度高度,但是坑的在于宽度和高度是没有单位的。没有单位意味着每个厂商都可以按照自己的期望随意给任意的值
因此有不同的触摸框厂商导入的时候就需要做好这部分的兼容,这部分仅仅是项目管理上的事情以及协议上的事情,和技术无关。但是做不好将会很坑
而触摸报告上来的宽度和高度其实有两个含义,一个含义是物理值,另一个含义是逻辑值。这两个值是什么意思?物理值就是触摸框物理收到了多大的面积,就报告多大。而逻辑值是根据当前屏幕的分辨率和尺寸等给定一个逻辑上计算出来的值,逻辑值主要是让不同的触摸框上报给应用一个大概相同的值
而应用显示触摸面积的大小也是一个神坑,原因是上面说的屏幕分辨率可不是系统分辨率。同时屏幕的大小和分辨率没有本质的联系。一个 10 寸的屏幕可以是 2k 分辨率,而一个 100 寸的屏幕可以是 1k 分辨率。而分辨率和像素相关,应用程序能控制的仅仅是像素。因此就需要应用程序知道当前运行过程中像素和物理尺寸的换算比例是多少,这部分需要应用程序和硬件配合,应用程序询问硬件当前的型号以及显示屏幕的尺寸。同时知道当前系统的分辨率,以此进行缩放,拿到当前像素和物理尺寸转换的参数。然后和触摸框部分协议报告上来的面积的含义,以此转换为实际渲染像素
需要注意的是 WPF 默认是像素无关的,这部分想要达到更好的控制,还需要了解 DPI 和分辨率的关系等细节。这部分请看下面博客
- 支持 Windows 10 最新 PerMonitorV2 特性的 WPF 多屏高 DPI 应用开发 - walterlv
- Windows 下的高 DPI 应用开发(UWP / WPF / Windows Forms / Win32) - walterlv
- Windows DPI Awareness for WPF - walterlv
协议文档
现在 HID 设备是有一套国际标准的协议,触摸和触笔也都有对应的协议。按照协议来可以减少很多坑,同时也能很好做到适配
详细请看 Windows 的 Pen 协议
而国际标准仅仅能做到的是很少的功能,有很多强大的功能还是需要触摸框配合作出私有协议,通过私有协议实现软硬件协同。在 WPF 中可以直接读取 HID 设备的方法读取触摸框的私有协议。但是触摸框 HID 默认会被系统独占,因此私有协议需要另开一路 USB 等设备才能做到
如果是多个触摸框屏幕想要在同一个应用上玩,默认的 Windows 是不支持的,此时需要用到读取裸数据的方法,请看 WPF 使用 RawInput 接收裸数据
触摸相关
在做触摸应用的时候,推荐阅读触摸相关的博客,详细请看
大概阅读完能理解之后,对于很多触摸问题也就知道如何解决了
现在 WPF 也是开源的,可以自己改动源代码,从最底层为自己的项目和硬件进行定制。如果构建 WPF 框架定制的版本请看 手把手教你构建 WPF 框架的私有版本
虫文
最后来和小伙伴讲个笑话
在 2018 的时候,我的师兄问我,潮汕这边有没一些手段可以驱邪。我问为什么?他说遇到了诡异的事情。是啥事情哇?每到夜里 12 点的时候,咱在测试触摸框写字的时候就会出现莫名奇妙的跳点。而在白天是没有任何问题的。他说他测试了半个月了,都是这样
我强撑陪着师兄到 12 点,此时广州的夏天蚊子又多,又不敢睡,只能打着呵欠数着时间。终于来到了 12 点,师兄说看好了,于是开始写字。刚开始没啥事,我就笑着说,开发一过来就不复现。还没说完,就发现了出现了一次跳点,出现了一次三角形的线。我切换到了某个单指触摸应用的时候,发现这个应用偶尔会触摸失效
这个就有趣了,早上测试的时候没有任何问题的,而且还是压测
我默默念了一句有名的咒语 天津津,地灵灵,宇古草,番薯藤 然后开始写一个不著名的测试程序 ManipulationDemo 的前版本。而师兄却无聊的在打蚊子
测试程序写完在大板运行的时候,却没有发现任何问题,整整半个晚上都没有复现问题
按照控制变量法,第二天晚上减少一个关键步骤。这次一开始就上测试程序,不能再念咒语了
一过 12 点就发现复现问题了,但是测试程序有点坑,没有找到问题。于是我又在改测试程序。而师兄在旁边继续打蚊子
也许是仅在 12 点附近在能复现问题,我测试程序改好之后就有再次复现。只能明天继续了
第三天没啥头绪,于是就去请教我的师傅,太子爷,太子爷当初的头像是名侦探,睿智的他给出了连逗比听起来也不太相信的理由
不过我是大逗比,所以就信了这个理由。于是改改测试程序,反过来推测写代码
到了晚上,还是在 12 点过后就复现了问题。好在有测试程序,这次通过日志发现了有莫名的触摸点从触摸框发送给了应用。而在某个单指触摸应用触摸失效偶尔失效的问题上,是偶尔会存在一个点在不断进行触摸。师兄架设起了摄像机,当初的他头发还在,还是担任着摄影组的组长。经过了多次的测试和对比,我的测试程序在屏幕上打出了所有触摸点的轨迹,对比拍到的视频,此时找到了本质的问题
小伙伴是否还记得说到红外触摸框的时候说的问题,没错,红外触摸框只要有物体挡住光线就会识别为触摸。虽然不同的厂商的灵敏度不相同,但是在广州的夏天晚上,会有很多蚊虫飞进来,在屏幕上飞过的时候就会触发。蚊虫触发了红外触摸框的触摸,因此就有跳点。而有不断的触摸产生是因为蚊虫在屏幕上面爬
但这不是标题虫文的故事,这个故事要从 2019 开始说。有一天祖师爷 cy 找到我问,小伙,你今年是不是还没有去旅游。我说是的。毕竟我不喜欢出去玩。祖师爷说,那好,给你个机会,收拾东西,和乔哥去内蒙古玩,那边有斯日带着你
既然祖师爷发话了,我只能告别死鱼 去了内蒙古玩。当然去到内蒙古玩的时候,就和扑街小说说的一样,一定会有诡异的事情。斯日导游告诉我说,他有几个设备如果晚上不关机,第二天起来就会自动打开白板软件,同时软件上面有看不懂的笔迹,很诡异
我觉得挺有趣的,就和斯日和乔哥组个队去看看是啥有趣的笔迹。到了之后我看到的好像是有人在大板上画了我也看不懂的文字,看起来不是蒙文,因为我大概知道蒙文是什么样。于是开了大板的摄像头,以为是有小伙伴在玩耍。结果第二天摄像头除了蚊虫啥都没拍到
我将拍到的那些诡异的文字发给了太子爷,太子一看说,这就是虫文的问题
原来蚊虫是喜欢光的,而大板如果没关的话,会在有触摸的时候亮屏。如果蚊子足够多,那么将会偶尔点开屏幕。屏幕亮了,就有更多的蚊子会在屏幕上面爬。而屏幕上的应用由做了处理,只需要单击就能打开,毕竟触摸屏上面双击的交互比较坑。因此蚊子可以打开白板应用,而蚊子在屏幕上面爬的时候就会写出虫文也就是人类应该是看不懂的笔迹
我在第二天的时候循楼,抓到了一只在写字的蚊子,那就没错了
在软件行业有很多玄学,但在掌握了原理之后就不是玄学了
更多请看 白板类应用的模式交互设计方案
本文会经常更新,请阅读原文: https://dotnet-campus.github.io//post/WPF-%E8%A7%A6%E6%91%B8%E5%B1%8F%E5%BA%94%E7%94%A8%E9%9C%80%E8%A6%81%E4%BA%86%E8%A7%A3%E7%9A%84%E7%9F%A5%E8%AF%86.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 lindexi (包含链接: https://dotnet-campus.github.io/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系 。