• .NET桌面程序混合开发之四:键盘事件的响应


    .NET桌面程序混合开发之四:键盘事件的响应

    1. 问题

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

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

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

    • 在窗体属性中,设置KeyPreview属性为Ture;
      enter description here
    • 在窗体事件中,为窗体添加KeyPress事件;
      enter description here
    • 在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.  
    3. public WebViewForm() 
    4. { 
    5. InitializeComponent(); 
    6. InitializeAsync(); 
    7.  
    8. listener.ScanerEvent += (s) => 
    9. { 
    10. webView.CoreWebView2.PostWebMessageAsString(s.Result); //将扫描结果交给页面 
    11. }; 
    12. } 
    • 当窗体打开时,在托管代码中安装钩子
    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.zip 10.59 KB

  • 相关阅读:
    大宗商品经营管理特点与风险节点
    大宗商品企业风险管理与套期会计课程
    推荐一个php7+ mongodb三方类
    利用Redis锁解决高并发问题
    PHP socket初探 --- 关于IO的一些枯燥理论
    Swoole 4.1.0 正式版发布,支持原生 Redis/PDO/MySQLi 协程化
    PHP利用Mysql锁解决高并发
    PHP AES cbc模式 pkcs7 128加密解密
    PHP 利用文件锁处理高并发
    Redis 应用场景【商品拼团抢购】
  • 原文地址:https://www.cnblogs.com/sammy621/p/15806948.html
Copyright © 2020-2023  润新知