1. 问题

在生产环境中,有一些场景需要窗体来响应键盘事件(注意,是窗体响应,而不是窗体上的控件响应),如解析扫码枪的扫描结果。但在嵌入WebView2的Form程序,Host Form无法对键盘事件(如窗体的KeyPress)进行截获,同样,也无法对WebView2本身进行键盘事件的响应处理。

2. 传统的键盘事件如何响应

在解决问题前,回顾一下在C#中,传统的窗体键盘事件如何响应。

  • 在窗体属性中,设置KeyPreview属性为Ture;
  • 在窗体事件中,为窗体添加KeyPress事件;
  • 在IDE为你自动添加的响应处理函数中,编写你的处理逻辑
  1. private void Form1_KeyPress(object sender, KeyPressEventArgs e)
  2. {
  3. //编写你的响应逻辑
  4. MessageBox.Show(e.KeyChar.ToString());
  5. }

而在嵌入WebView2的Form程序,Form对键盘事件,无法按照传统处理方式进行截获,也就无法按照原来的处理方式处理了。

3. 问题产生的原因

先来梳理一下窗体响应事件的顺序。

  • 当窗体上没有任何其他控件的时候,窗体是可以直接响应这些消息的,也就是说可以正常响应键盘事件。
  • 但是当窗体存在其他控件后,我们会发现窗体再也不会响应按键消息了,因为这些消息都由其上的控件所处理掉并且不再发给父窗体。
  • 通过Form类的KeyPreview的属性,它是可以接收得到按键消息。也就是第2部分提到的处理方式

分析到这里,基本上能找到webView2加入后引发的怪异行为了。总结起来就是:WebView2拦截了键盘事件。为什么WebView2要这么做?因为WebView本看上是浏览器内核,它要通过最高级别的键盘事件处理一些浏览器事件。如F5刷新,F12调试等,你会发现,哪怕焦点不在webView上,WebView2仍然能响应F5的刷新事件。当然,浏览器的快捷键可以被禁止,但这是另一话题。不可否认的事实就是:WebView影响了消息传递机制。微软可能也意识到这个问题,但对于浏览器的快捷键与用户自定义按键事件的协调,确实是个头疼的事情。这部分是我的猜测。

4. 问题的解决

托管(managed)方式的消息响应失效,尝试非托管方式的处理。思路是:调用Win32的钩子函数,对键盘事件进行拦截,同时将扫描行为进行包装,将获得到的扫描结果(以回边键为结束符),返回托管调用方。

  • 编写单独的ScanerHook类,处理扫描键盘事件。
  • 托管代码,通过注册ScanerEvent事件响应函数,来接收扫描结果。在WinForm中的关键代码如下:
  1. private ScanerHook listener = new ScanerHook();
  2. public WebViewForm()
  3. {
  4. InitializeComponent();
  5. InitializeAsync();
  6. listener.ScanerEvent += (s) =>
  7. {
  8. webView.CoreWebView2.PostWebMessageAsString(s.Result); //将扫描结果交给页面
  9. };
  10. }
  • 当窗体打开时,在托管代码中安装钩子
  1. private void WebViewForm_Load(object sender, EventArgs e)
  2. {
  3. listener.Start();
  4. }
  • 在窗体关闭时,不要忘记卸载钩子
  1. private void WebViewForm_FormClosed(object sender, FormClosedEventArgs e)
  2. {
  3. listener.Stop();
  4. }

至此,页面已经“具备了”扫描条码(二维码)的能力。示例代码是在VS2022,用.net6实现的。

 dotnet6form.zip10.59 KB

 

.NET桌面程序混合开发之四:键盘事件的响应的更多相关文章

  1. Hybrid小程序混合开发之路 - 数据交互

    HTML+CSS是历史悠久.超高自由度.控制精准.表现能力极强.编码简单.学习门槛超低.真跨平台的一种UI界面开发方式. 本文介绍的是微信小程序和H5混合开发的一种数据交互方式. 很多应用在原生界面中 ...

  2. Android软键盘事件imeOptions响应

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 在android发开过程中,有时候需要对EditText的软键盘进行监听. 当点击软键盘回车位置按键的时候,需要实现 完成.前进.下 ...

  3. linux系统下,在用户空间应用程序中模拟发送系统键盘事件

    Linux 有自己的 input 子系统,可以统一管理鼠标和键盘事件. 如果想模拟键盘事件,但是系统没有键盘设备该如何是好? 基于输入子系统实现的 input 可以方便的在用户空间模拟鼠标和键盘事件. ...

  4. 小程序-云开发 bindscroll滚动事件执行setData()方法,导致scroll-view视图抖动

    需求描述 想做一个类似京东小程序首页功能列表左右滑动的效果,效果图如下 遇到的问题 1. 如何让scroll-view显示两行 做过小程序开发的都知道,scroll-view要么显示一行,可以左右滚动 ...

  5. Mac开发如何处理键盘事件

    Mac上输入与手机输入的不同是,Mac需要处理更多的键盘交互,因为Mac上的键盘输入会有多种快捷键组合. 代理方法处理 NSTextField #pragma mark - NSTextFieldDe ...

  6. iOS自动处理键盘事件的第三方库:IQKeyboardManager

    我们写界面要考虑很多用户体验问题,键盘事件的响应就是比较麻烦的一种.我们需要监听键盘事件,考虑点击背景收起键盘.考虑键盘遮挡输入框问题等等,而且每个界面都要做这么一套.这个库帮我们解决了这个事情. 这 ...

  7. IQKeyboardManager 自动处理键盘事件的第三方库

    我们写界面要考虑很多用户体验问题,键盘事件的响应就是比较麻烦的一种.我们需要监听键盘事件,考虑点击背景收起键盘.考虑键盘遮挡输入框问题等等,而且每个界面都要做这么一套.这个库帮我们解决了这个事情. 这 ...

  8. WinForm下的键盘事件(KeyPress、KeyDown)及如何处理不响应键盘事件

    KeyDown事件用来处理功能键:F1 F2 F3... keyPress事件用来处理字符比如说:A B C... 1 2 3... 注:处理该事件时,需要先将窗体的 KeyPreview=true; ...

  9. JavaFX桌面应用开发-鼠标事件和键盘事件

    鼠标相关事件的操作初始代码 package application; import javafx.application.Application;import javafx.event.ActionE ...

  10. .NET混合开发解决方案9 WebView2控件的导航事件

    系列目录     [已更新最新开发文章,点击查看详细] WebView2控件应用详解系列博客 .NET桌面程序集成Web网页开发的十种解决方案 .NET混合开发解决方案1 WebView2简介 .NE ...

随机推荐

  1. 直播预告丨Hello HarmonyOS进阶课程第三课——游戏开发实践

    为了帮助初识HarmonyOS的开发者快速入门,我们曾推出Hello HarmonyOS系列一共5期课程,从最基础的配置IDE和创建Hello World开始,详细介绍HarmonyOS基础.开发环境 ...

  2. mongodb基础整理篇————索引[四]

    前言 简单介绍一些索引. 正文 索引的术语: index 索引 key 键 DataPage 数据页 covered Query: ixscan/collscan: big O Natation: q ...

  3. mm系列权重文件瘦身

    瘦身脚本: (会在resnet50.pth文件的同级目录下生成一个resnet50_thin.pth) import os import torch root_dir = os.getcwd() de ...

  4. ST语言

    CODESYS平台的ST语言笔记 前言: 基于汇川plc软件,底层是CODESYS平台.这回ST语言正儿八经要用 所以要学,做笔记是为了梳理加深基础要点印象,顺便分享交流学习.codesys平台包括汇 ...

  5. 《c#高级编程》第2章C#2.0中的更改(二)——匿名类型

    一.概念 C#中的匿名类型是一种特殊类型,可以在运行时动态创建一个对象,该对象可以包含多个属性,这些属性的名称和类型可以在创建时指定.相对于定义具体的类,匿名类型更加灵活和简洁. C#的匿名类型通常用 ...

  6. ArcPy自动绘制大量地图并设置地图要素:Python

      本文介绍基于Python语言中ArcPy模块,实现ArcMap自动批量出图,并对地图要素进行自定义批量设置的方法. 1 任务需求   首先,我们来明确一下本文所需实现的需求.   现有通过Pyth ...

  7. Beetl 源码解析:GroupTemplate 类

    本文首发于公众号:腐烂的橘子 前言 Beetl 是一款 Java 模板引擎,在公司的项目中大量运用,它的作用是写通用代码时,有一些差异化的逻辑需要处理,这时可以把这些差异化的逻辑写在模板里,程序直接调 ...

  8. [ABC342D] Square Pair 题解

    [题目描述] 给定一个长度为 \(N\) 的非负整数序列 \(A=\left(A_1,\cdots,A_n\right)\).求满足以下条件的整数对 \(\left(i,j\right)\) 的数量. ...

  9. 看见云上新力量|专访快准车服CIO牛小虎:全面信息化支持,让车爱上快准

    简介: 从"数字化汽配基础设施的创造者"到"让车爱上快准",快准车服的探索与前行执著而坚定!基于数字化能力,面向3万亿的未来市场,我们拭目以待!--快准车服CI ...

  10. [GPT] Vue 的 methods 中使用了 addEventListener,如何在 addEventListener 的匿名函数参数中访问 Vue data 变量

      在 Vue 的 methods 方法中使用 addEventListener时,你可以使用 箭头函数 来访问 Vue 实例的数据. 箭头函数不会创建自己的作用域,而是继承父级作用域的上下文.以下是 ...