我想改變一箇舊的代碼鍵盤鉤爲更好的支持Unicode字符(舊代碼是ascii),在這一刻我有困難,以捕獲WM_KEYDOWN
事件。如何通過Windows鉤子捕獲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;
爲什麼您使用'WH_JOURNALRECORD'而不是'WH_KEYBOARD'或'WH_KEYBOARD_LL'?而你的'KBHookProc()'使用'_Msg',而不先分配任何東西。爲什麼不處理'WM_CHAR' /'WM_UNICHAR'窗口消息而不是'WM_KEYDOWN'鍵盤消息?如果您只是爲自己的應用程序處理鍵盤輸入,請改用「TApplication.OnMessage」。如果您要掛鉤其他應用程序,請考慮使用[原始輸入API](https://msdn.microsoft.com/en-us/library/windows/desktop/ms645536.aspx),而不要使用「SetWindowsHookEx()」。 –
@RemyLebeau,我編輯了我的問題。爲什麼沒有寫入文件? – Saulo
我似乎記得原生的Delphi文件函數不能很好地處理Unicode。除此之外,你是否做過任何調試,以確認你調用的所有API函數返回你期望的結果?我在這裏沒有看到任何錯誤檢查代碼。 –