拦截并取消DirectX游戏的按键事件

Intercept and cancel key press events for DirectX game

本文关键字:事件 游戏 DirectX 取消      更新时间:2023-10-16

我正在为DirectX游戏开发一个小工具,我想防止用户在一定时间内按下某个键(本例中为F12)。

我可以找到很多模拟按键的选项,但在游戏读取之前取消按键的选项是什么?

语言其实并不重要,尽管我更喜欢C#或C++解决方案,或者只是朝着正确的方向推动:)

提前感谢!

好消息是,我以前做过这件事,所以我可以说这是可能的,而且确实有效。

坏消息是这并不简单。它需要大量复杂的代码,可能需要很长时间才能实现,但我将解释如何做到这一点

像DirectX游戏这样的应用程序通常注册原始输入。由于你想阻止键盘事件到达应用程序,你需要一种方法在原始输入和游戏之间插入代码,这样你就可以检查原始输入并决定是否允许它传递到游戏:

因此,您想更改以下流程:

Raw Input --> Game

Raw Input --> Your Code --> Game

在无法访问游戏源代码的情况下,您必须找到插入代码的方法。

当有键盘输入可用时,游戏将调用WinAPI函数GetRawInputData,该函数将告诉它键盘事件。理想情况下,我们想要的是,当游戏调用这个函数时,它实际上调用了我们的代码,而不是WinAPI函数。然后我们可以决定告诉游戏关于键盘事件的内容,我们可以告诉它任何我们想要的内容(例如忽略F12)。听起来不错吧?这就是它变得有趣的地方。。。

我们可以利用windows如何将可执行文件加载到内存中。通常,程序使用(或"导入")对其他dll(如User32.dll中的GetRawInputData)中的函数的调用。当程序加载到内存中时,Windows将在一个表(导入地址表(IAT))中填充指向相应dll中可执行代码的指针。这意味着当程序调用函数时,它会被引导到内存中User32.dll中的可执行代码来运行它

如果我们可以将我们的一个函数的地址写入/补丁到该表中,这样当游戏调用GetRawInputData时,它实际上会指向我们的函数供我们处理,那不是很好吗?我们可以!它被称为导入地址表修补。

这里有一篇关于它的非常好的文章,其中包含一些C++中的工作代码。你应该先阅读它,更详细地了解它是如何工作的,然后你可以修改它来支持你的需求。它会起作用,但我知道这可能比你所希望的更多的工作(更多的工作),但本质上你是在入侵应用程序,这从来都不容易做到

这是值得做的,即使只是为了更好地了解幕后的Windows。

祝你好运!

编辑

正如Simon所说,如果游戏不使用原始输入,Windows Hooks是一种更简单的方法。DirectX游戏往往是一种特殊情况,与标准挂钩的效果并不太好,因为它们使用特殊的方法从用户那里获得输入。不过,无论如何,如果它有效的话,它会容易得多。