1

I'm wanting change a old code of keyboard hook for one better with support to unicode characters ( old code is ascii) and in this moment i have trouble to capture WM_KEYDOWN event.

My actual code is the following:

var
  Form1: TForm1;
   HookHandle: hHook;
   ft: text;

implementation

{$R *.dfm}

function KBHookProc(Code: Integer; WParam: WParam; LParam: LParam)
  : LRESULT; stdcall;
var
  _Msg: TMessage;
  VK: Integer;
  SC: Integer;
  buf: Char;
  KS: TKeyboardState;
  MyHKB: HKL;
begin
  if Code = HC_ACTION then
  begin
 if _Msg.Msg = WM_KEYDOWN then
  begin
    VK := _Msg.WPARAM;
    MyHKB := GetKeyboardLayout(_Msg.LParam);
    SC := MapVirtualKeyEx(VK, MAPVK_VK_TO_VSC, MyHKB);
    GetKeyboardState(KS);
    ToUnicodeEx(VK, SC, KS, @buf, sizeof(buf), 0, MyHKB);

         append(ft);

             write(ft,buf);
           closefile(ft);
         MyHKB := 0;
    end;
  end;
  Result := CallNextHookEx(HookHandle, Code, WParam, LParam);
end;


procedure TForm1.FormCreate(Sender: TObject);
begin
  assignfile(ft,'log.txt');
    rewrite(ft);
    closefile(ft);

  HookHandle := SetWindowsHookEx(WH_JOURNALRECORD , @KBHookProc, hinstance, 0);
end;

EDIT 1:

My code below is capturing WM_KEYDOWN with success, but nothing is written to file :-(.

Some suggestion?

var
  Form1: TForm1;
   HookHandle: hHook;
   ft: text;

implementation

{$R *.dfm}

function LowLevelKeyboardProc(nCode: Integer; wParam: wParam;
    lParam: lParam): LRESULT; stdcall;
  var
  _Msg: TMessage;
  VK: Integer;
  SC: Integer;
  buf: Char;
  KS: TKeyboardState;
  MyHKB: HKL;
begin
  if (nCode >= 0) and (wParam = WM_KEYDOWN) then
  begin
    VK := _Msg.WParam;
    MyHKB := GetKeyboardLayout(_Msg.LParam);
    SC := MapVirtualKeyEx(VK, MAPVK_VK_TO_VSC, MyHKB);
    GetKeyboardState(KS);
    ToUnicodeEx(VK, SC, KS, @buf, sizeof(buf), 0, MyHKB);

         append(ft);

             write(ft,buf);
           closefile(ft);
         MyHKB := 0;
  end;
  Result := CallNextHookEx(HookHandle, nCode, wParam, lParam);
end;

function InstallHook: Boolean;
begin
  Result := False;
  if HookHandle = 0 then
  begin
    HookHandle := SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, 0, 0);
    Result := HookHandle <> 0;
  end;
end;

function UninstallHook: Boolean;
begin
  Result := UnhookWindowsHookEx(HookHandle);
  HookHandle := 0;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  assignfile(ft,'log.txt');
    rewrite(ft);
    closefile(ft);

   InstallHook;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  UninstallHook;
end;
  • 1
    Why are you using `WH_JOURNALRECORD` instead of `WH_KEYBOARD` or `WH_KEYBOARD_LL`? And your `KBHookProc()` is using `_Msg` without assigning anything to it first. Why not handle `WM_CHAR`/`WM_UNICHAR` window messages instead `WM_KEYDOWN` keyboard messages? If you are just handling keyboard input for your own app, use `TApplication.OnMessage` instead. If you are going to hook other apps, consider using the [Raw Input API](https://msdn.microsoft.com/en-us/library/windows/desktop/ms645536.aspx) instead of `SetWindowsHookEx()`. – Remy Lebeau Dec 06 '16 at 03:39
  • @RemyLebeau, i edited my question. Why nothing is written to file? –  Dec 06 '16 at 03:48
  • I seem to recall that the native Delphi file functions don't handle Unicode well. Besides that, have you done any debugging to confirm that *all* of the API functions you call return what you expect them to? I don't see any error-checking code here. – Rob Kennedy Dec 06 '16 at 04:33
  • Your second code still reads uninitialized `_Msg`. – Rob Kennedy Dec 06 '16 at 04:36

0 Answers0