SetWindowsHookEx创建一个本地钩子.如何使其全球化?

Mar*_*ski 9 delphi hook winapi setwindowshookex

在Delphi XE应用程序中,我正在尝试设置一个全局挂钩来监视焦点更改.钩子是在一个DLL中创建的:

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

在同一个DLL中,我有一个将消息发布到主机应用程序窗口的钩子过程:

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;
Run Code Online (Sandbox Code Playgroud)

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

我想这与DLL的多个实例注入其他进程有关.有与所接受的答复类似的问题在这里,但它是C,我不是很知道怎样才能做同样的德尔福DLL(如注记语句来设置共享内存).

(这主要是一个概念证明,但我仍然想让它发挥作用.我需要知道在我的应用程序通过点击,alt +标签,激活热键等方式激活之前,哪个窗口处于活动状态.问题就是如果使用鼠标或alt + tab,GetForegroundWindow总是会返回我自己的应用程序的窗口句柄,无论我把它放多久,例如挂钩应用程序的主要消息队列.所以钩子似乎是唯一可行的解​​决方案,尽管我真的不喜欢这个主意.)

All*_*uer 15

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

  • 在这个特定情况下,每个具有自己的数据的DLL都可能出现问题.但是,OP可能不需要使用共享内存:上面代码的一个简单修复就是给目标窗口一个特定的类名,并让钩子代码使用FindWindow来找到该目标.另外,钩子的另一个限制是:32位钩子只能挂钩到32位代码; 同样是64位; 因此,挂钩32位和64位进程可能会有问题. (2认同)