Search code examples
delphikeyboardmousevcl

Delphi block Keyboard & Mouse


How to block keyboard & mouse separately? I tried with BlockInput, it doesn't work in Windows 10 and also tried with as following:

function KBHookHandler(ACode: Integer; WParam: WParam; LParam: LParam)
  : LResult; stdcall;
begin
  if ACode < 0 then
    // Immediately pass the event to next hook
    Result := CallNextHookEx(Hook, ACode, WParam, LParam)
  else
    // by setting Result to values other than 0 means we drop/erase the event
    Result := 1;
end;

function DisableKeyboard : boolean;
begin
  if Hook = 0 then
    // install the hook
    // Hook := SetWindowsHookEx(WH_KEYBOARD, @KBHookHandler, HINSTANCE, 0);
    Hook := SetWindowsHookEx(WH_KEYBOARD, @KBHookHandler, 0, 0);
  Result := Hook <> 0;
end;

My requirement is block keyboard and mouse separately in Windows 7, Windows 8 & Windows 10.


Solution

  • You posted this same question on Embarcadero's Delphi NativeAPI forum, so I will give you the same answer I posted there.

    The only way to block the mouse and keyboard separate is to use separate keyboard and mouse hooks.

    BlockInput() works on Windows 10. But it blocks all input, you can't be selective with it.

    When hooking other processes than your own, your hook MUST be in a DLL, and you must pass the DLL's hinstance to the 3rd parameter of SetWindowsHookEx():

    An error may occur if the hMod parameter is NULL and the dwThreadId parameter is zero or specifies the identifier of a thread created by another process.

    By specifying 0 for the hMod, the callback will only work in the calling process, since that is the only process that will have access to the callback. When you set the dwThreadId parameter to 0 to hook multiple threads globally, hMod must point to a DLL that can be injected into other processes.

    Also, you may need separate 32bit and 64bit DLLs in order to properly hook 32bit and 64bit processes, respectively. But do make sure that the thread installing the hook has a message loop:

    This hook may be called in the context of the thread that installed it. The call is made by sending a message to the thread that installed the hook. Therefore, the thread that installed the hook must have a message loop.

    Because hooks run in the context of an application, they must match the "bitness" of the application. If a 32-bit application installs a global hook on 64-bit Windows, the 32-bit hook is injected into each 32-bit process (the usual security boundaries apply). In a 64-bit process, the threads are still marked as "hooked." However, because a 32-bit application must run the hook code, the system executes the hook in the hooking app's context; specifically, on the thread that called SetWindowsHookEx. This means that the hooking application must continue to pump messages or it might block the normal functioning of the 64-bit processes.

    If a 64-bit application installs a global hook on 64-bit Windows, the 64-bit hook is injected into each 64-bit process, while all 32-bit processes use a callback to the hooking application.

    To hook all applications on the desktop of a 64-bit Windows installation, install a 32-bit global hook and a 64-bit global hook, each from appropriate processes, and be sure to keep pumping messages in the hooking application to avoid blocking normal functioning. If you already have a 32-bit global hooking application and it doesn't need to run in each application's context, you may not need to create a 64-bit version. {quote}

    The reason you are not able to lock out the entire system is because you are not hooking the entire system correctly to begin with.