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

流媒体机器人模拟按键失效:如何适配各类游戏与应用?

关于SendInput模拟按键兼容性问题的解决方案

核心问题分析

部分游戏或应用会采用DirectInput或自定义输入钩子捕获按键,这类程序往往优先响应硬件级扫描码而非虚拟键;还有些会通过输入上下文(如时间戳、额外信息)判断输入是否来自真实硬件,导致常规模拟失效。

针对性优化方案

  • 优先使用扫描码,弱化虚拟键:
    你的代码同时传入了wVk和wScan,但很多游戏会忽略虚拟键。建议设置KEYEVENTF_SCANCODE标志,仅填充wScan并将wVk设为0,同时区分按键按下(无额外标志)和释放(追加KEYEVENTF_KEYUP)。
  • 填充真实时间戳:
    真实硬件输入的time字段会包含系统时间,当前设为0可能被部分应用判定为模拟输入。可以用GetTickCount()获取系统运行时间填充该字段。
  • 确保权限与窗口焦点:
    • 程序需以管理员权限运行,部分游戏会拒绝普通权限的输入模拟请求。
    • 模拟前调用SetForegroundWindow将目标窗口设为前台,SendInput默认向当前焦点窗口发送输入,若目标窗口未获焦点,输入会直接失效。
  • 无需通过PID定向发送:
    Windows没有直接通过PID发送输入的API,正确做法是先通过FindWindow/EnumWindows结合PID或窗口标题获取目标窗口句柄,将其设为前台后再发送输入。

优化后的代码片段

use windows::Win32::{
    UI::Input::KeyboardAndMouse::{
        SendInput, INPUT, INPUT_0, KEYBD_EVENT_FLAGS, INPUT_KEYBOARD, KEYBDINPUT,
        KEYEVENTF_SCANCODE, KEYEVENTF_KEYUP
    },
    System::Threading::GetTickCount,
};

fn simulate_scan_key(scan_code: u16, is_press: bool) {
    let mut flags = KEYBD_EVENT_FLAGS(KEYEVENTF_SCANCODE.0);
    if !is_press {
        flags |= KEYBD_EVENT_FLAGS(KEYEVENTF_KEYUP.0);
    }

    let input = INPUT {
        r#type: INPUT_KEYBOARD,
        Anonymous: INPUT_0 {
            ki: KEYBDINPUT {
                wVk: 0,          // 虚拟键设为0,仅使用扫描码
                wScan: scan_code,
                dwFlags: flags,
                time: unsafe { GetTickCount() }, // 填充系统运行时间
                dwExtraInfo: 0,
            },
        },
    };

    unsafe {
        SendInput(
            &[input],
            std::mem::size_of::<INPUT>().try_into().unwrap(),
        );
    }
}

额外注意事项

  • 部分反作弊系统(如Easy Anti-Cheat、Battle Eye)会直接拦截SendInput,这类情况无法通过常规方法解决,需查看反作弊开发者文档是否提供白名单机制。
  • 测试时覆盖不同类型应用:DirectX游戏、Unity游戏、普通桌面程序,逐一验证兼容性。

内容的提问来源于stack exchange,提问作者Jab

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 17:35:28