• .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. 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

     

     
  • 相关阅读:
    Spring注解
    [Exception Android 22]
    Android中Word转Html
    [Exception Android 20]
    POI-word转html
    【JS设计模式】装饰者模式
    C语言中的传值调用
    Spring Aop基础总结
    Android开发-状态栏着色原理和API版本号兼容处理
    9.12測试(二)——国际象棋
  • 原文地址:https://www.cnblogs.com/webenh/p/16055130.html
Copyright © 2020-2023  润新知