• cefsharp + winform 内嵌网页的触屏输入焦点问题


    原文

    现象

    我正在使用 cefsharp + winform 建立一个桌面程序用于显示网页。但程序启动后触屏点击网页中的输入框,使用键盘输入,文字输入不进去。win + D 最小化程序后,再恢复窗口才能正常输入。

    临时措施

    //在 form loaded 事件里设置焦点
    ChromiumWebBrowser.GetBrowser().GetHost().SetFocus(true);
    

    又出现新问题

    程序在使用过程中,偶尔又会出现输入不进去的问题,win + D 最小化程序后,再恢复窗口才能正常输入。

    可能因为什么操作又丢失了焦点。但 ChromiumWebBrowser.GetBrowser().GetHost() 没有失去焦点事件,找不到好的事机再次使用临时措施(SetFocus)。

    Google 了一圈找到几个方案。

    方案一 FocusHandler(无效)

    browser.FocusHandler 属性设置为 null

    对于我的问题无效。没有解决

    方案二 关闭多线程消息循环(有效

    这个方法对于我的问题有效,即使我不使用临时措施设置 SetFocus ,输入也一切正常。我猜测那个偶发的新问题应该也不会再出现,待后续观察!

    而在官方论坛中这个 bug 被标记为不修复 ,所以即使升级版本也没用,有同样问题的同学可以试试这个方法。

    Program.cs/Main 内

    CefSettings settings = new CefSettings();
    settings.CefCommandLineArgs["multi-threaded-message-loop"] = "0";
    settings.MultiThreadedMessageLoop = false;
    Cef.Initialize(settings);
    Application.Idle += Application_Idle;
    
    //Application_Idle
    private static void Application_Idle(object sender, EventArgs e)
    {
        Cef.DoMessageLoopWork();
    }
    

    方案三 升级内核版本(无效)

    Cefsharp - keyboard not working until refocus

    答案里提到这个问题已经在 version 81 中修复。我目前使用的是 73 版本。

    于是升级到 81.3.10 版本。观察使用了几天,依旧出现偶尔输入不进去的问题

    方案四 设置主程序的 ExStyle(无效)

    继承 ChromiumWebBrowser 重写

    public class MyWebBrowser : ChromiumWebBrowser
        {
            public MyWebBrowser(string address, IRequestContext requestContext = null) : base(address, requestContext)
            {
            }
    
            const uint WS_EX_NOACTIVATE = 0x08000000;
    
            protected override IWindowInfo CreateBrowserWindowInfo(IntPtr handle)
            {
                var info = base.CreateBrowserWindowInfo(handle);
                info.ExStyle &= WS_EX_NOACTIVATE;
                return info;
            }
        }
    

    方案五 提取屏幕键盘(无效)

    之前屏幕键盘是一个control,在主程序的form中显示,现在提取成一个单独项目编译成 exe。设置键盘的窗口不抢焦点,就像输入法界面那样

    但已验证该方案没有效果,但我也保留这个修改,作为键盘的功能优化。

    public partial class KeyboardForm : Form
        {
            public KeyboardForm()
            {
                InitializeComponent();
            }
    
            private const int WS_EX_TOOLWINDOW = 0x00000080;
            private const int WS_EX_NOACTIVATE = 0x08000000;
    
            protected override CreateParams CreateParams
            {
                get
                {
                     const int WS_CHILD = 0x40000000;
                    CreateParams cp = base.CreateParams;
                    cp.ExStyle |= (WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW);
    
                    return cp;
                }
            }
        }
    
  • 相关阅读:
    [转]Splay算法
    [转]模拟退火算法
    [转]九种背包问题
    [转]C++实现平衡二叉树
    关于set
    __builtin_popcount
    为什么调用线程的join方法,等待的是执行join方法的线程
    volatile and 指令重排序 (单例模式用volatile来声明单例对象)
    线程池
    sts 转用 IDEA随记
  • 原文地址:https://www.cnblogs.com/ohzxc/p/15750206.html
Copyright © 2020-2023  润新知