CefSharp技术问题:点击输入框后如何获取反馈?
嘿,我之前在Unity里用CefSharp做离屏浏览器交互时也碰到过一模一样的需求,给你几个亲测有效的解决方案:
方法1:通过JS事件监听+C#回调获取输入框激活通知
这是最直接的方式,在网页里注入脚本监听输入框的focus事件,触发时通知Unity端唤起键盘。
步骤1:注册C#回调对象给JS调用
在Unity初始化CefSharp离屏浏览器后,注册一个供JS调用的C#对象:
// 假设你的CefSharp浏览器实例是browser browser.JavascriptObjectRepository.Register( "UnityInputBridge", new InputBridgeHandler(browser), isAsync: false, options: BindingOptions.DefaultBinder );
步骤2:实现C#回调处理类
这个类负责接收JS的通知,然后在Unity主线程唤起键盘:
public class InputBridgeHandler { private readonly IWebBrowser _browser; public InputBridgeHandler(IWebBrowser browser) { _browser = browser; } public void OnInputFocused(string elementSelector) { // CefSharp的回调可能在子线程,必须切到Unity主线程操作UI/键盘 UnityMainThreadDispatcher.Instance.Enqueue(() => { // 唤起Unity系统键盘(如果是移动端用TouchScreenKeyboard,PC可以用自定义弹窗) var keyboard = TouchScreenKeyboard.Open("", TouchScreenKeyboardType.Default); // 键盘输入完成后,把内容同步回网页输入框 keyboard.onDone += inputText => { if (!string.IsNullOrEmpty(inputText)) { _browser.ExecuteScriptAsync($"document.querySelector('{elementSelector}').value = '{inputText}';"); } }; }); } }
注:UnityMainThreadDispatcher是用来在子线程调用主线程方法的工具,你可以自己实现一个简单版本,或者用Unity Asset Store里的现成工具。
步骤3:注入JS监听输入框事件
在网页加载完成后,注入脚本监听所有可输入元素的focus事件:
browser.FrameLoadEnd += (sender, args) => { if (args.Frame.IsMain) { args.Frame.ExecuteJavaScriptAsync(@" // 监听input、textarea以及可编辑元素的focus事件 const watchElements = document.querySelectorAll('input, textarea, [contenteditable=true]'); watchElements.forEach(el => { el.addEventListener('focus', () => { // 给Unity传递元素的选择器(如果没有id,用tag+name组合也可以) const selector = el.id ? `#${el.id}` : `${el.tagName.toLowerCase()}[name='${el.name}']`; window.UnityInputBridge.OnInputFocused(selector); }); }); // 处理动态加载的输入框(比如异步渲染的内容) const observer = new MutationObserver(mutations => { mutations.forEach(mutation => { mutation.addedNodes.forEach(node => { if (node.nodeType === Node.ELEMENT_NODE) { const newInputs = node.querySelectorAll('input, textarea, [contenteditable=true]'); newInputs.forEach(el => { el.addEventListener('focus', () => { const selector = el.id ? `#${el.id}` : `${el.tagName.toLowerCase()}[name='${el.name}']`; window.UnityInputBridge.OnInputFocused(selector); }); }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); "); } };
方法2:通过CefSharp鼠标点击事件判断元素类型
如果你不想依赖JS注入,也可以通过自定义IMouseHandler来捕获点击事件,然后判断点击的元素是否是可输入类型。
实现自定义MouseHandler
public class CustomMouseHandler : IMouseHandler { private readonly IWebBrowser _browser; public CustomMouseHandler(IWebBrowser browser) { _browser = browser; } public bool OnMouseClick(IWebBrowser chromiumWebBrowser, IBrowser browser, MouseEvent mouseEvent) { // 点击后,通过JS获取点击位置的元素 browser.MainFrame.ExecuteJavaScriptAsync($@" const clickedEl = document.elementFromPoint({mouseEvent.X}, {mouseEvent.Y}); const isInputElement = clickedEl.tagName === 'INPUT' || clickedEl.tagName === 'TEXTAREA' || clickedEl.isContentEditable; if (isInputElement) {{ const selector = clickedEl.id ? `#${clickedEl.id}` : `${clickedEl.tagName.toLowerCase()}[name='${clickedEl.name}']`; window.UnityInputBridge.OnInputFocused(selector); }} "); return false; } // 其他IMouseHandler接口方法默认实现 public bool OnMouseDown(IWebBrowser chromiumWebBrowser, IBrowser browser, MouseEvent mouseEvent) => false; public void OnMouseMove(IWebBrowser chromiumWebBrowser, IBrowser browser, MouseEvent mouseEvent) {} public bool OnMouseUp(IWebBrowser chromiumWebBrowser, IBrowser browser, MouseEvent mouseEvent) => false; public bool OnMouseWheel(IWebBrowser chromiumWebBrowser, IBrowser browser, MouseEvent mouseEvent, int deltaX, int deltaY) => false; public bool OnMouseLeave(IWebBrowser chromiumWebBrowser, IBrowser browser) => false; }
绑定MouseHandler到浏览器
browser.MouseHandler = new CustomMouseHandler(browser);
注意事项
- 如果输入框没有
id或name,可以用xpath或者其他唯一标识来定位元素,避免同步内容时出错。 - 对于PC端,你可以用Unity的
InputField模拟键盘,而不是TouchScreenKeyboard。 - 一定要确保所有Unity UI操作都在主线程执行,否则会出现报错或无响应的情况。
内容的提问来源于stack exchange,提问作者Perazim
相关产品推荐
相关产品推荐

