Delphi 了解如何使用Windows挂钩

Delphi 了解如何使用Windows挂钩,delphi,winapi,hook,setwindowshookex,Delphi,Winapi,Hook,Setwindowshookex,我正在尝试使用SetWindowsHookEx在某些过程中钩住鼠标。我在用Delphi7。 代码(DLL): 所以。SetWindowsHookEx返回1428错误:无法设置没有模块句柄的非本地钩子。 但正如我所知,如果我不需要使用dll hmodule。。。 我知道它将如何工作: 每个鼠标事件都将使用WM_数据(wParam是事件数据,lParam是ProcessId)传递到我的应用程序(窗口类是'ichookapplication') 谢谢 WH_鼠标是一个全局钩子。DLL将被注入钩住的进程

我正在尝试使用SetWindowsHookEx在某些过程中钩住鼠标。我在用Delphi7。 代码(DLL):

所以。SetWindowsHookEx返回1428错误:无法设置没有模块句柄的非本地钩子。 但正如我所知,如果我不需要使用dll hmodule。。。 我知道它将如何工作: 每个鼠标事件都将使用WM_数据(wParam是事件数据,lParam是ProcessId)传递到我的应用程序(窗口类是'ichookapplication')


谢谢

WH_鼠标是一个全局钩子。DLL将被注入钩住的进程中。您确实需要提供一个模块句柄。与错误代码相关的名称非常清楚,
error\u HOOK\u NEEDS\u HMOD
。提供模块句柄并不困难。通过
HInstance


如果您不想注射,那么您需要使用
WH\u MOUSE\u ll
而不是
WH\u MOUSE

谢谢!Im修改HookThreadId并将Dll模块句柄传递给CallNextHookEx。代码运行良好。除非您确实有令人信服的理由挂接单个进程,否则通常应使用而不是SetWindowsHookEx()来接收鼠标和键盘输入。顺便提一下,
WH_MOUSE
回调通常在安装它的线程的上下文中运行,因此在回调中调用
GetCurrentProcessId()
将返回应用程序的进程ID,而不是挂接的应用程序的进程ID。
function MouseProc(code: integer; wParam: WPARAM; lParam: LPARAM)
  : LongInt; stdcall;
var
  AppWnd: HWND;
begin
  Result := 0;
  if (code < 0) then
    Result := CallNextHookEx(HookHandle, code, wParam, lParam)
  else begin
    AppWnd := FindWindowW('ichookapplication', nil);
    SendMessage(AppWnd, MW_MOUSEHOOKED,  wParam, GetCurrentProcessId);
    Result := CallNextHookEx(HookHandle, code, wParam, lParam);
  end;
end;

procedure HookThreadId(theadId: Cardinal) export; stdcall;
var
  e: DWORD;
begin
  HookHandle := SetWindowsHookEx(WH_MOUSE, @MouseProc, 0, theadId);
  if (HookHandle = 0) then
  begin
    e := GetLastError;
    MessageBox(0, 'error', PAnsiChar(IntToStr(e)), MB_OK);
  end;
end;
//loading code
if (dll = 0) then
  begin
    dll := LoadLibrary('mhook.dll');
    @Hook := nil;
    @SetThreadHook := nil;
  end;
  if (dll > HINSTANCE_ERROR) then
  begin
    pH := GetProcAddress(dll, 'Hook');
    @Hook := pH;
    pSth := GetProcAddress(dll, 'HookThreadId');
    @SetThreadHook := pSth;
  end;

// attach code
h := FindWindow(nil, 'Form1');
  terminalProc := GetWindowThreadProcessId(h, nil);
  if (terminalProc = 0) then
  begin
      ShowMessage(IntToStr(GetLastError));
     Exit;
  end;


SetThreadHook(terminalProc);