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

如何通过Tauri与纯JS实现虚拟键盘字符插入至当前聚焦窗口?

如何通过Tauri与纯JS实现虚拟键盘字符插入至当前聚焦窗口?

嘿,我刚好折腾过类似的虚拟键盘需求,你的问题核心其实是点击虚拟键盘按键时,Tauri窗口会抢走焦点,导致原来的目标窗口(比如记事本、浏览器)失去焦点,自然收不到输入。别担心,分两种场景给你靠谱的解决方案:

一、全局虚拟键盘(给所有系统窗口用)

这种情况必须靠Rust的系统级输入模拟来实现,因为JS只能操作自己的窗口,没法跨窗口发送输入。我们可以用enigo这个跨平台的键盘模拟库,配合Tauri的自定义命令来搞定:

步骤1:Rust端配置

首先在src-tauri/Cargo.toml里添加依赖:

[dependencies]
enigo = "0.2.0" # 用最新稳定版即可
tauri = { version = "1.5", features = ["api-all"] }

然后在src-tauri/src/main.rs里注册一个自定义命令,用来接收前端传过来的字符并模拟输入:

use enigo::{Enigo, KeyboardControllable, Key};
use tauri::command;

// 自定义命令:接收要发送的字符,模拟系统键盘输入
#[command]
fn send_input(char: &str) {
    let mut enigo = Enigo::new();
    // 处理特殊按键(比如回车、退格)
    match char {
        "Enter" => enigo.key_click(Key::Return),
        "Backspace" => enigo.key_click(Key::Backspace),
        _ => enigo.key_sequence(char),
    }
}

fn main() {
    tauri::Builder::default()
        .invoke_handler(tauri::generate_handler![send_input])
        .run(tauri::generate_context!())
        .expect("运行Tauri应用出错");
}

步骤2:前端JS调用

给你的虚拟键盘按键绑定点击事件,点击时调用上面的Rust命令:

// 假设每个按键元素都有data-key属性存要输入的内容(普通字符或特殊按键名)
document.querySelectorAll('.key-btn').forEach(btn => {
    btn.addEventListener('click', async () => {
        const keyValue = btn.dataset.key;
        if (keyValue) {
            try {
                await window.__TAURI__.invoke('send_input', { char: keyValue });
            } catch (err) {
                console.error('发送输入失败:', err);
            }
        }
    });
});

注意事项

  • 权限问题:macOS上需要给你的应用开启「辅助功能」权限(系统设置→隐私与安全性→辅助功能),否则没法模拟系统输入;Windows和Linux一般不需要额外权限。
  • 特殊按键可以直接通过Enigo的Key枚举来处理,比如Tab、Shift这些都支持。

二、应用内虚拟键盘(只给自己的Tauri应用输入框用)

如果你的虚拟键盘只给自身应用的输入框用,那可以通过控制Tauri窗口的焦点来解决,避免点击按键时抢走输入框的焦点:

步骤1:配置窗口不抢焦点

在src-tauri/tauri.conf.json里修改窗口配置,让虚拟键盘窗口默认不获取焦点:

"windows": [
    {
        "title": "应用内虚拟键盘",
        "width": 500,
        "height": 150,
        "decorations": false,
        "alwaysOnTop": true,
        "focus": false, // 关键:窗口启动时不获取焦点
        "transparent": true,
        "skipTaskbar": true
    }
]

步骤2:前端插入字符

因为输入框还保持着焦点,点击按键时直接找到当前聚焦的输入元素,插入字符即可:

document.querySelectorAll('.key-btn').forEach(btn => {
    btn.addEventListener('click', () => {
        const char = btn.dataset.char;
        if (!char) return;
        
        // 获取当前聚焦的输入元素
        const activeElement = document.activeElement;
        if (activeElement && (activeElement.tagName === 'INPUT' || activeElement.tagName === 'TEXTAREA')) {
            // 插入字符到光标位置
            const start = activeElement.selectionStart;
            const end = activeElement.selectionEnd;
            const value = activeElement.value;
            activeElement.value = value.substring(0, start) + char + value.substring(end);
            // 恢复光标位置
            activeElement.selectionStart = activeElement.selectionEnd = start + char.length;
            // 触发输入事件,确保表单能捕获到变化
            activeElement.dispatchEvent(new Event('input'));
        }
    });
});

这种方案不需要依赖Rust库,纯JS就能搞定,适合应用内的场景。

备注:内容来源于stack exchange,提问作者Commodore64

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 16:24:30