delphi - SetWindowsHookEx 创建本地 Hook 。如何使其全局化?

标签 delphi winapi hook setwindowshookex

在 Delphi XE 应用程序中,我试图设置一个全局 Hook 来监视焦点变化。钩子(Hook)是在 dll 中创建的:

focusHook := SetWindowsHookEx( WH_CBT, @FocusHookProc, HInstance, 0 );
// dwThreadId (the last argument) set to 0 should create a global hook

在同一个 dll 中,我有一个钩子(Hook)过程,它将消息发布到主机应用程序窗口:

function FocusHookProc( code : integer; wParam: WPARAM; lParam: LPARAM ) : LResult; stdcall;
begin
  if ( code < 0 ) then
  begin
    result := CallNextHookEx( focusHook, code, wParam, lParam );
    exit;
  end;

  result := 0;

  if ( code = HCBT_SETFOCUS ) then
  begin
    if ( hostHWND <> INVALID_HANDLE_VALUE ) then
      PostMessage( hostHWND, cFOCUSMSGID, wParam, lParam );
  end;
end;

这可行,但主机仅接收应用程序本身内焦点更改的通知。主窗体上有一个备忘录和几个 TButton,在它们之间切换焦点会产生预期的消息。然而,应用程序本身之外的任何焦点变化都不会被报告。

我认为这与 DLL 的多个实例被注入(inject)到其他进程有关。有一个类似的问题并已接受回复here ,但它是针对 C 的,我不太明白如何在 Delphi dll 中执行相同的操作(例如用于设置共享内存的 pragma 语句)。

(这主要是一个概念证明,但我仍然想让它发挥作用。我需要知道在我的应用程序通过单击 alt+tab 激活之前哪个窗口处于事件状态,问题是,如果使用鼠标或 alt+tab,GetForegroundWindow 总是返回我自己的应用程序的窗口句柄,无论我放置得有多早,例如通过 Hook 应用程序的主消息队列。所以 Hook 看起来像唯一可行的解​​决方案,尽管我不太喜欢这个想法。)

最佳答案

由于 DLL 被注入(inject)到另一个进程中,因此除了正在调试的进程之外,您不会遇到任何断点命中。此外,其他进程中的每个 DLL 实例也获取自己的全局/静态数据。如果 hostHWND 是全局值,则它在另一个进程中的值将与在本进程中的值不同。事实上它甚至不会被初始化。您需要使用共享内存块在进程之间共享值。可能需要使用共享互斥体和其他同步对象来确保任何共享内存写入都受到保护。最后,如果您使用的是 Windows Vista+,则只有具有相同访问级别及更低访问级别的进程才会注入(inject) DLL。 IOW,如果您以登录用户身份运行该进程,则只有以登录用户身份运行的进程才会注入(inject)该 DLL。

关于delphi - SetWindowsHookEx 创建本地 Hook 。如何使其全局化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9550074/

相关文章:

Delphi 10 Seattle update1 IDE 高 dpi 支持

c++ - Windows 上的 native 窄字符串编码是什么?

c++ - 读取进程内存

c# - 在 Winforms 中捕获 WinKey+D 键序列

delphi - 是否可以仅基于 BPL/DCP,针对未检查 "Build With Runtime Packages"的 BPL/DCP 构建 EXE 项目?

delphi - Delphi 2010 中的 TIdHashSHA1.HashStream 是否损坏?

c++ - 纯 Win32 C++ 中的自定义菜单边框(无 WTL、MFC 等)

c++ - WH_SHELL 的问题

hook - 当应用程序启动时,是否有我可以 Hook 的 Windows 消息?

delphi - 如何获取名称中也包含点的目录的子文件夹名称?