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. 力扣378(java&python)-有序矩阵中第 K 小的元素(中等)

    题目: 给你一个 n x n 矩阵 matrix ,其中每行和每列元素均按升序排序,找到矩阵中第 k 小的元素.请注意,它是 排序后 的第 k 小元素,而不是第 k 个 不同 的元素. 你必须找到一个 ...

  2. OAM 深入解读:OAM 为云原生应用带来哪些价值?

    导读:OAM 是阿里巴巴联合微软在社区推出的一款用于构建和交付云原生应用的标准规范,旨在通过全新的应用定义.运维.分发与交付模型,推动应用管理技术向"轻运维"的方向迈进,全力开启下 ...

  3. 深入浅出eBPF|你要了解的7个核心问题

    简介: 过去一年,ARMS基于eBPF技术打造了Kubernetes监控,提供多语言无侵入的应用性能,系统性能,网络性能观测能力,验证了eBPF技术的有效性.eBPF技术和生态发展很好,未来前景广大, ...

  4. 从托管到原生,MPP架构数据仓库的云原生实践

    ​简介:本文介绍了云原生数据仓库产品AnalyticDB PostgreSQL从Cloud-Hosted到Cloud-Native的演进探索,探讨为了实现真正的资源池化和灵活售卖的底层设计和思考,涵盖 ...

  5. [Caddy2] Caddyfile 概念预览

    结构 块: 所有的指令必须在 { } 块中,如果只有一个站点,则块标记可以省略. 全局的配置块可以放在最上方,其次是站点的配置块. 指令: 指令是服务于站点配置的关键词. 关键词和引号: 空格在 Ca ...

  6. WPF 获取全局所有窗口的创建显示事件 监控窗口打开

    本文将告诉大家如何在 WPF 里面进行全局监控任意的窗口创建显示打开,可以获取到每个 WPF 窗口的打开的时机.如此可以用来辅助定位问题和输出日志 这篇博客是有背景的,老司机告诉我说他的应用不响应鼠标 ...

  7. 2018-6-30-dotnet-设计规范-·-抽象类

    title author date CreateTime categories dotnet 设计规范 · 抽象类 lindexi 2018-6-30 9:2:38 +0800 2018-06-30 ...

  8. 临时容器ephermeral(20)

    一.临时容器ephermeral概述 参考官方文档: https://kubernetes.io/zh/docs/concepts/workloads/pods/ephemeral-container ...

  9. js实现一个拖拽效果(本例vue中),边界限定,获取鼠标坐标,div坐标

    有事没事搞个图: demo: <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...

  10. Docker的Portainer认识、安装、使用

    一.认识 docker的图形化界面 Portainer 是一个轻量级的容器管理界面,可以让用户更轻松地管理 Docker 容器.镜像.网络和数据卷等.Portainer 提供了一个用户友好的 Web ...