LowLevelKeyboardProc() never is executed

回眸只為那壹抹淺笑 提交于 2021-02-08 10:40:37

问题


I'm need hook my keyboard and found the following code (reference here) that i want use in a Delphi Console project. Happens that after the first test i noted that LowLevelKeyboardProc() function never is executed (hello never is displayed on console window). Already SetWindowsHookEx() is working fine and returning <> 0.

Then someone can help me to solve this problem please?

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  Windows,
  Messages,
  SysUtils;

function ToUnicodeEx(wVirtKey, wScanCode: UINT; lpKeyState: PByte; pwszBuff: PWideChar; cchBuff: Integer; wFlags: UINT; dwhkl: HKL): Integer; stdcall; external 'user32.dll';

const
  LLKHF_ALTDOWN = KF_ALTDOWN shr 8;
  WH_KEYBOARD_LL = 13;

type
  PKBDLLHOOKSTRUCT = ^TKBDLLHOOKSTRUCT;

  TKBDLLHOOKSTRUCT = packed record
    vkCode: DWORD;
    scanCode: DWORD;
    flags: DWORD;
    time: DWORD;
    dwExtraInfo: DWORD;
  end;

var
  llKeyboardHook: HHOOK = 0;
  AltDown, ShiftDown, CtrlDown: Boolean;
  KeyBoardState: TKeyboardState;
  KeyBoardLayOut: HKL;

function TranslateVirtualKey(VirtualKey: integer): WideString;
begin
  Result := '';
  {$Region 'Translate VirtualKey'}
  case VirtualKey of
    VK_RETURN:   Result := sLineBreak;
    VK_TAB:      Result := '     ';
    VK_BACK:     Result := '[BackSpace]';
    VK_SHIFT:    Result := '[Shift]';
    VK_CONTROL:  Result := '[Ctrl]';
    VK_MENU:     Result := '[Alt]';
    VK_ESCAPE:   Result := '[Esc]';
    VK_PAUSE:    Result := '[Pause]';
    VK_CAPITAL:  Result := '[Caps Lock]';
    VK_PRIOR:    Result := '[Page Up]';
    VK_NEXT:     Result := '[Page Down]';
    VK_END:      Result := '[End]';
    VK_HOME:     Result := '[Home]';
    VK_LEFT:     Result := '[Left Arrow]';
    VK_UP:   Result := '[Up Arrow]';
    VK_RIGHT:    Result := '[Right Arrow]';
    VK_DOWN:     Result := '[Down Arrow]';
    VK_SELECT:   Result := '[Select]';
    VK_PRINT:    Result := '[Print Screen]';
    VK_EXECUTE:  Result := '[Execute]';
    VK_SNAPSHOT: Result := '[Print]';
    VK_INSERT:   Result := '[Ins]';
    VK_DELETE:   Result := '[Del]';
    VK_HELP:     Result := '[Help]';
    VK_F1:       Result := '[F1]';
    VK_F2:   Result := '[F2]';
    VK_F3:   Result := '[F3]';
    VK_F4:   Result := '[F4]';
    VK_F5:   Result := '[F5]';
    VK_F6:   Result := '[F6]';
    VK_F7:   Result := '[F7]';
    VK_F8:   Result := '[F8]';
    VK_F9:   Result := '[F9]';
    VK_F10:      Result := '[F10]';
    VK_F11:      Result := '[F11]';
    VK_F12:      Result := '[F12]';
    VK_NUMPAD0:  Result := '0';
    VK_NUMPAD1:  Result := '1';
    VK_NUMPAD2:  Result := '2';
    VK_NUMPAD3:  Result := '3';
    VK_NUMPAD4:  Result := '4';
    VK_NUMPAD5:  Result := '5';
    VK_NUMPAD6:  Result := '6';
    VK_NUMPAD7:  Result := '7';
    VK_NUMPAD8:  Result := '8';
    VK_NUMPAD9:  Result := '9';
    VK_SEPARATOR:Result := '+';
    VK_SUBTRACT: Result := '-';
    VK_DECIMAL:  Result := '.';
    VK_DIVIDE:   Result := '/';
    VK_NUMLOCK:  Result := '[Num Lock]';
    VK_SCROLL:   Result := '[Scroll Lock]';
    VK_PLAY:     Result := '[Play]';
    VK_ZOOM:     Result := '[Zoom]';
    VK_LWIN,
    VK_RWIN:     Result := '[Win Key]';
    VK_APPS:     Result := '[Menu]';
  end;
   {$EndRegion}
end;

function LowLevelKeyboardProc(nCode: Integer; wParam: wParam; lParam: lParam): HRESULT; stdcall;
var
  pkbhs: PKBDLLHOOKSTRUCT;
  AChr: array[0..1] of WideChar;
  VirtualKey: integer;
  ScanCode: integer;
  ConvRes: integer;
  ActiveWindow: HWND;
  ActiveThreadID: DWord;
  Str: widestring;
begin
  pkbhs := PKBDLLHOOKSTRUCT(Pointer(lParam));
  if nCode = HC_ACTION then
  begin
    VirtualKey := pkbhs^.vkCode;

    Str := '';
    if LongBool(pkbhs^.flags and LLKHF_ALTDOWN) and (not AltDown) then
    begin
      Str := '[Alt]';
      AltDown := True;
    end;
    if (not LongBool(pkbhs^.flags and LLKHF_ALTDOWN)) and (AltDown) then
      AltDown := False;

    if (WordBool(GetAsyncKeyState(VK_CONTROL) and $8000)) and (not CtrlDown) then
    begin
      Str := '[Ctrl]';
      CtrlDown := True;
    end;
    if (not WordBool(GetAsyncKeyState(VK_CONTROL) and $8000)) and (CtrlDown) then
      CtrlDown := False;

    if ((VirtualKey = VK_LSHIFT) or (VirtualKey = VK_RSHIFT)) and (not ShiftDown) then
    begin
      Str := '[Shift]';
      ShiftDown := True;
    end;
    if (wParam = WM_KEYUP) and ((VirtualKey = VK_LSHIFT) or (VirtualKey = VK_RSHIFT)) then
      ShiftDown := False;

    if (wParam = WM_KEYDOWN) and ((VirtualKey <> VK_LMENU) and (VirtualKey <> VK_RMENU)) and (VirtualKey <> VK_LSHIFT) and (VirtualKey <> VK_RSHIFT) and (VirtualKey <> VK_LCONTROL) and (VirtualKey <> VK_RCONTROL) then
    begin
      Str := TranslateVirtualKey(VirtualKey);
      if Str = '' then
      begin
        ActiveWindow := GetForegroundWindow;
        ActiveThreadID := GetWindowThreadProcessId(ActiveWindow, nil);
        GetKeyboardState(KeyBoardState);
        KeyBoardLayOut := GetKeyboardLayout(ActiveThreadID);
        ScanCode := MapVirtualKeyEx(VirtualKey, 0, KeyBoardLayOut);
        if ScanCode <> 0 then
        begin
          ConvRes := ToUnicodeEx(VirtualKey, ScanCode, @KeyBoardState, @AChr, SizeOf(AChr), 0, KeyBoardLayOut);
          if ConvRes > 0 then
            Str := AChr;
        end;
      end;
    end;
    if Str <> '' then
      writeln('hello!');
  end;
  Result := CallNextHookEx(llKeyboardHook, nCode, wParam, lParam);
end;

begin
  try
    llKeyboardHook := SetWindowsHookEx(WH_KEYBOARD_LL, @LowLevelKeyboardProc, HInstance, 0);
    Writeln(llKeyboardHook);
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

回答1:


Your code is not giving the hook a chance to trigger. Your code's actual execution begins with assigning a hook:

llKeyboardHook := SetWindowsHookEx(WH_KEYBOARD_LL, @LowLevelKeyboardProc, HInstance, 0);

Then you write out that handle to the user:

Writeln(llKeyboardHook);

Assuming no exception was raised, the very next thing is waiting for user input:

Readln;

At this point, suppose a user presses a key on the keyboard and presses enter. That causes ReadLn to exit, thus exiting the code and terminating the application. So the hook never has a chance to actually fire.

You should be doing some sort of wait after creating the hook, such as processing Windows messages.



来源:https://stackoverflow.com/questions/57260687/lowlevelkeyboardproc-never-is-executed

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!