现象
我正在使用 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;
}
}
}