You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 03:54:05