如何使用C++程序为微软模拟飞行X(FSX)实现截图功能
现有模拟按键方案的问题和修复方法
- 缺少按键弹起事件
你当前的SendInput代码只发送了F12按下的事件,没有发送按键弹起事件,Steam的截图逻辑需要检测完整的按下+弹起动作才会触发,正确的代码写法如下:
INPUT input[2] = {}; // 按下F12 input[0].type = INPUT_KEYBOARD; input[0].ki.wVk = VK_F12; // 弹起F12 input[1].type = INPUT_KEYBOARD; input[1].ki.wVk = VK_F12; input[1].ki.dwFlags = KEYEVENTF_KEYUP; UINT sendResult = SendInput(ARRAYSIZE(input), input, sizeof(INPUT)); // 正常情况下sendResult应返回2,代表两个输入事件都成功发送
- 窗口焦点问题
Steam的截图热键仅对当前处于前台激活状态的游戏窗口生效,发送按键前需要先通过FindWindow匹配FSX的窗口标题获取窗口句柄,再调用SetForegroundWindow将游戏窗口切到前台。 - 权限隔离问题
如果你的FSX是用管理员权限启动的,普通权限运行的程序发送的模拟按键会被Windows的UIPI(用户界面特权隔离)机制拦截,无法传递到游戏进程,测试时请将你的程序也设置为以管理员身份运行。
替代截图方案
如果模拟按键的方案依然不符合你的需求,可以尝试以下两种不依赖Steam功能的实现思路:
- 挂钩D3D9的
EndScene方法:FSX基于DirectX 9开发,你可以注入到游戏进程挂钩IDirect3DDevice9::EndScene接口,在接口调用时直接读取后台帧缓存的像素数据存为图片,该方案不需要窗口处于前台,也不受热键设置影响,兼容性最高。 - 使用Windows Graphics Capture API:Win10 1803及以上系统自带的截图API,不需要注入进程,只要获取到FSX的窗口句柄就能直接捕获窗口内容,哪怕窗口被其他界面遮挡也可以正常截图,实现难度低,也不会出现反作弊误判的问题。
内容的提问来源于stack exchange,提问作者Kevin
相关产品推荐
相关产品推荐

