I have this code. I am writing a global keyboard interceptor.

library ScanFlow1; uses Windows, SysUtils; var CurrentHook: HHook; function KeyboardProc(nCode: integer; wParam: integer; lParam: integer ): LongWord; stdcall; begin if (nCode < 0) then begin Result := CallNextHookEx(CurrentHook, nCode, wParam, lParam); Exit; end; //Что то делаем ... Result := CallNextHookEx(CurrentHook, nCode, wParam, lparam); end; procedure SetupGlobalKeyBoardHook; begin CurrentHook := SetWindowsHookEx(WH_KEYBOARD, @KeyboardProc, HInstance, 0); end; procedure UnHook; begin UnhookWindowshookEx(CurrentHook); end; exports SetupGlobalKeyBoardHook, UnHook; begin end. 

And I see that it works in separate applications. In Notepad ++, in the browser and some others it does not work, but in just Notepad it works. What is wrong here? Is this a global hook?

  • Can the browser and notepad ++ put their own hooks and do not make CallNextHookEx ? - kot-da-vinci

2 answers 2

The solution found in the installation of another function CurrentHook := SetWindowsHookEx(WH_KEYBOARD_LL, @KeyboardProc, HInstance, 0);

 function KeyboardProc(Code, wParam, lParam: Integer): Integer; stdcall; var zKeyState: TKeyBoardState; zChr: Char; zCount: Integer; zHookInfo : PKBDLLHOOKSTRUCT; begin Result := CallNextHookEx(CurrentHook, Code, wParam, lParam); if Code <> HC_ACTION then Exit; zHookInfo := Pointer(lParam); if (zHookInfo^.flags And LLKHF_UP) <> 0 then begin GetKeyboardState(zKeyState); zCount := ToAscii(zHookInfo.vkCode, zHookInfo.scanCode, zKeyState, @zChr, 0); if zCount = 1 then if DestHandle <> 0 then SendMessage(DestHandle, Msg, Ord(zChr), 0); end; end; 

    If you install a hook via SetWindowsHookEx , then the third parameter is the DLL handle (HMODULE / HINSTANCE). This DLL will be loaded into each process if the hook to be installed is global.

    In particular, this means that your trap will not work for 64-bit processes (meaning that your DLL is 32-bit) - because a 32-bit DLL cannot be loaded into a 64-bit process (and vice versa).

    In other words, to set a truly global trap, you need to write two applications and two DLLs, 32 and 64 bits. And install / remove them at the same time.

    The solution with WH_KEYBOARD_LL is incorrect. Indeed, low-level traps are not embedded in the process , so the bit width of the DLL will not matter. But it also means that the global trap will be executed in the context of your application, and not the application in which the event occurs. Of course, such an operation with context switching has its price. Low-level traps are very expensive - if possible, do not use them.