【问题标题】:Passing 'this' pointer to MouseProc of SetWindowsHookEx将“this”指针传递给 SetWindowsHookEx 的 MouseProc
【发布时间】:2023-03-30 20:23:01
【问题描述】:

一般来说,每当我们想在 C++ 对象中包装一个窗口/线程时,我们通过通过SetWindowLong/GetWindowLongSetProp/GetProp 传递this 指针来实现窗口,并作为lpParameter 传递CreateThread /等等。

我的问题是针对 Hooks 的。 将“this”指针传递给 SetWindowsHookEx 的回调过程的优雅方法是什么,或者换句话说如何包装钩子的回调过程?

由于 SetWindowsHookEx 不接受任何 UserData 参数,因此除了使用未封装的即全局/静态/TLS 数据之外,我没有看到太多选择。

【问题讨论】:

  • @RogerLipscombe - 感谢您的链接。我已经看到了,它谈到了使用静态,我已经知道/已经做过很多次了。但从未觉得它令人满意。
  • 这并不令人满意,但这是“标准”的方式。如果你做其他事情,那可能会令人惊讶。
  • @RogerLipscombe 你是说使用@ybungalobill 提到的Thunks 可能令人惊讶吗?我想敞开心扉,学习新的更好的方法来做同样的事情。
  • 我的意思是:如果您正在编写一个框架(例如 ATL),那么使用 thunk 可能是正确的答案。如果您正在编写应用程序,那么更喜欢简单(但不是“优雅”)的解决方案。

标签: c++ c winapi hook


【解决方案1】:

您应该只有一个给定钩子的实例,因此全局数据不是问题。

如果您正在开发一个允许多个可动态添加或删除的钩子实例的库,请不要在操作系统级别添加多个钩子。相反,添加一个遍历钩子实例列表的库级钩子过程。由于您维护此列表,因此您可以跟踪所需的每个条目旁边的任何“用户数据”。

【讨论】:

  • 全局映射是我要避免的,最终它是一个全局变量/在封装之外。
  • @subdeveloper:是的,对不起,我第一次阅读问题时正在考虑子类化(窗口消息挂钩)。我想这次我已经理解了您的实际要求。
  • 很高兴你做到了!.. 有人没有将我的问题发布为重复 :)
【解决方案2】:

“最优雅的方法”是使用 thunk。它是运行时生成的一小段代码,其中包含您的 this 指针。这是 ATL 甚至用于常规窗口的方法。

【讨论】:

  • 理论上很优雅,但在实践中这涉及许多未定义的行为,不可移植,并且可能会触发防病毒。
  • @BenVoigt:这就是 所有 ATL 的工作原理。永远不会绊倒防病毒软件。它与您的 Windows 应用程序一样便携。
  • 感谢您的指点,我相信我已经阅读了有关 thunk 的内容,特别是 ATL 过去是如何使用它的。我同意它的优雅,但可能你会同意它的肮脏工作,并且可能难以维护。还是您有其他建议?
  • @IInspectable:你有一个如何将有状态的 lambda 传递给 winapi 函数的例子吗?我想看看。
  • @IInspectable:链接代码使用单例静态,一次最多支持一个 lambda。这与只有一个全局变量持有一个指向你的类的唯一实例的指针是一样的。
猜你喜欢
  • 2016-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多