Delphi 如何通过Windows钩子捕获WM_KEYDOWN事件?

Delphi 如何通过Windows钩子捕获WM_KEYDOWN事件?,delphi,keyboard-hook,Delphi,Keyboard Hook,我想把键盘钩子的旧代码改成一个更好的支持unicode字符的代码(旧代码是ascii),现在我很难捕获WM_KEYDOWN事件 我的实际代码如下: var Form1: TForm1; HookHandle: hHook; ft: text; implementation {$R *.dfm} function KBHookProc(Code: Integer; WParam: WParam; LParam: LParam) : LRESULT; stdcall; va

我想把键盘钩子的旧代码改成一个更好的支持unicode字符的代码(旧代码是ascii),现在我很难捕获
WM_KEYDOWN
事件

我的实际代码如下:

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;
编辑1:

下面的代码成功地捕获了
WM_KEYDOWN
,但没有写入文件:-(

有什么建议吗

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;
var
表1:TForm1;
钩柄:hHook;
ft:文本;
实施
{$R*.dfm}
函数LowLevelKeyboardProc(nCode:Integer;wParam:wParam;
lParam:lParam):LRESULT;stdcall;
变量
_Msg:TMessage;
VK:整数;
SC:整数;
buf:Char;
KS:TKeyboardState;
MyHKB:HKL;
开始
如果(nCode>=0)和(wParam=WM_KEYDOWN),则
开始
VK:=_Msg.WParam;
MyHKB:=GetKeyboardLayout(_Msg.LParam);
SC:=MapVirtualKeyx(VK,MAPVK_VK_TO_VSC,MyHKB);
GetKeyboardState(KS);
ToUnicodeEx(VK,SC,KS,@buf,sizeof(buf),0,MyHKB);
附加(ft);
写入(ft,buf);
关闭文件(ft);
MyHKB:=0;
结束;
结果:=CallNextHookEx(HookHandle、nCode、wParam、lParam);
结束;
函数InstallHook:Boolean;
开始
结果:=假;
如果HookHandle=0,则
开始
HookHandle:=SetWindowsHookEx(WH_KEYBOARD_LL,LowLevelKeyboardProc,0,0);
结果:=0;
结束;
结束;
函数:布尔;
开始
结果:=unhookwindowshookx(钩柄);
钩子句柄:=0;
结束;
过程TForm1.FormCreate(发送方:TObject);
开始
赋值文件(ft,'log.txt');
重写(ft);
关闭文件(ft);
安装挂钩;
结束;
程序TForm1.FormDestroy(发送方:ToObject);
开始
卸载挂钩;
结束;

为什么要使用
WH\u journal record
而不是
WH\u KEYBOARD
WH\u KEYBOARD\u LL
?以及
KBHookProc()
正在使用
\u Msg
而不首先为其分配任何内容。为什么不处理
WM\u CHAR
/
WM\u UNICHAR
窗口消息而不是
WM\u KEYDOWN
键盘消息?如果您只是为自己的应用程序处理键盘输入,请使用
TApplication.OnMessage
。如果您要挂接其他应用程序,请n使用而不是
SetWindowsHookEx()命令命令
@RemyLebeau,我编辑了我的问题。为什么没有写入文件?我似乎记得本机Delphi文件函数不能很好地处理Unicode。除此之外,您是否进行过任何调试以确认您调用的所有API函数都返回了您期望的结果?我在这里没有看到任何错误检查代码。您的第二个代码仍然可以读取未初始化的
\u Msg
。为什么要使用
WH\u journal record
而不是
WH\u KEYBOARD
WH\u KEYBOARD\u LL
?和
KBHookProc()
正在使用
\u Msg
而不首先为其分配任何内容。为什么不处理
WM\u CHAR
/
WM\u UNICHAR
窗口消息而不是
WM\u KEYDOWN
键盘消息?如果您只是为自己的应用程序处理键盘输入,请使用
TApplication.OnMessage
。如果您要挂接其他应用程序,请n使用而不是
SetWindowsHookEx()命令命令
@RemyLebeau,我编辑了我的问题。为什么没有写入文件?我似乎记得本机Delphi文件函数不能很好地处理Unicode。除此之外,您是否进行过任何调试以确认您调用的所有API函数都返回了您期望的结果?我在这里没有看到任何错误检查代码。您的第二个代码仍然可以读取未初始化的
\u Msg