【问题标题】:KeyboardProc returning TRUE causes performance dropsKeyboardProc 返回 TRUE 会导致性能下降
【发布时间】:2009-06-27 15:07:58
【问题描述】:

我正在为游戏的插件开发一个界面。我不能使用游戏 API(有几个原因,包括代码必须与游戏无关),我需要从用户那里获取键盘输入,所以我决定使用键盘挂钩 (WH_KEYBOARD) 来处理用户满足特定条件时输入。
问题是,虽然我可以正确接收和处理输入,但当我的钩子返回 TRUE 而不是 CallNextHookEx 时,系统似乎需要花费大量时间(远超过 800 毫秒)才能让事情按预期进行,这是不可接受的因为它甚至不允许流畅的打字体验。
我必须实现的是阻止按键消息到达 WndProc,所以问题是:我可以做些什么来实现我的目标,而不会对游戏性能造成太大影响,以至于结果将是不可接受的?
编辑:由于特定要求(使用反作弊的游戏可能会在我的代码中产生问题,尽管它与作弊无关)子类化活动的 wndproc 不是一种选择。

【问题讨论】:

    标签: c++ windows winapi hook


    【解决方案1】:
    1. 首先,您需要通过挂钩或any other way 将 DLL 注入目标进程。

    2. 找到感兴趣的窗口句柄。

    3. 调用GetWindowLongPtr(wnd, GWLP_WNDPROC)获取该窗口的当前窗口过程,并保存。

    4. 通过调用 SetWindowLongPtr(wnd, GWLP_WNDPROC, &NewWndProc) 对窗口进行子类化,其中 NewWndProc 是您的 DLL 实现的消息过程。

    在 NewWndProc 中,您需要处理键盘消息(有十几个,在 MSDN 索引中键入“键盘输入”,我不能发布超过 1 个链接)。对于其余的 windows 消息,调用您在 (3) 中保存的原始窗口过程,并返回它返回的值。不要直接调用,用 CallWindowProc 代替。

    这种方式不是很可靠,一些杀毒和反bot(例如“warden client”)软件可能不喜欢它,调试可能会很困难。

    但是它应该可以工作。

    【讨论】:

    • 感谢您的聪明建议,但正如您指出的那样,反作弊者不会喜欢这个,虽然我这样做不是为了作弊,但我真的无法承受触发误报的后果。键盘钩子的好处是反作弊不会标记它,因为许多程序将它用于合法目的......
    • Windows 子类化也被许多程序用于合法目的。
    【解决方案2】:

    键盘钩子不应该让事情变得那么慢。可能还有其他原因导致 800 毫秒延迟。如果你的钩子什么都不做,只返回 TRUE,它仍然很慢吗?

    【讨论】:

    • 是的,即使我处理键盘事件对性能没有任何影响,仅返回 TRUE 就足以导致速度下降,同时返回 FALSE (但这对我来说不合适,因为我处理的按键不应该由游戏处理)。我在两个不同引擎的不同游戏上测试过,结果是一样的。
    【解决方案3】:

    如果您想阻止消息到达 WndProc,那么您需要使用SetWindowLong 进行子类化,这样您将能够捕获所有消息并决定是否继续它们的路由。

    【讨论】:

    • 谢谢,但如上所述,子类化不是一种选择。
    【解决方案4】:

    尽管我不喜欢回答自己的问题,但我已经找到了延迟的原因。我测试过我的代码的游戏的消息泵是用一段时间(PeekMessage){GetMessage...}实现的,并且以某种方式删除键盘输入消息会导致GetMessage阻塞一段时间。使用 PostMessage 和 WM_NULL 有助于防止 GetMessage 阻塞。

    【讨论】:

      猜你喜欢
      • 2012-04-17
      • 1970-01-01
      • 2023-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多