使用典型的WH_KEYBOARD钩子来捕捉击键。它在WinXP中运行良好,但在Win7 +中存在问题 - 如果控制应用程序睡眠或挂起,它也会挂起钩住的窗口,即使使用了Postmessage 。这是一个已知的问题吗?我需要从钩子窗口中使消息处理程序异步....(目前正在使其他应用程序冻结并等待,如果我的应用程序正在做一些繁重的操作)。当我将dll记录到txt文件时,我在KeyboardProc中看不到任何挂起..
hook lib
library myHook
...
function KeyboardProc(Code : Integer; wParam : WPARAM; lParam : LPARAM): LRESULT; stdcall;
const
SysKeys: set of Byte = [8, 9, 13, 27];
var
KeyDown: Boolean;
KeyChar: WideChar;
rslt: LongBool;
ta: integer;
begin
if Code = HC_ACTION then
begin
KeyDown := (lParam and (1 shl 31)) = 0;
if KeyDown then
begin
if not (wParam in SysKeys) and GetKeyboardState(Keyboard) then
begin
kl := GetKeyboardLayout(GetWindowThreadProcessId(GetForegroundWindow, nil));
ta := ToUnicodeEx(wParam, (lParam and $00FF0000) shr 16, @Keyboard, @KeyChar, 1, 0, kl);
end
else
ta := 0;
if ta = 1 then
rslt := PostMessage(DestHandle, WM_KEYHOOK, SourceHandle, Ord(KeyChar))
else
rslt := PostMessage(DestHandle, WM_EXKEYHOOK, SourceHandle, lParam);
end;
end;
Result := CallNextHookEx(KeyboardHook, Code, wParam, lParam);
end;
function StartListen: Boolean; export stdcall;
begin
try
KeyboardHook := SetWindowsHookEx(WH_KEYBOARD, @KeyboardProc, HInstance, 0);
Result := True;
except
Result := False;
end;
end;
function StopListen: Boolean; export stdcall;
begin
if KeyboardHook > 0 then UnhookWindowsHookEx(KeyboardHook);
Result := True;
end;
....
exports
StartListen, StopListen;
begin
DestHandle := FindWindow(shcHookWndClass, nil);
end;
我的类启动挂钩和接收消息
constructor TSysHook.Create(AOwner: TComponent);
begin
inherited;
FWindowHandle := CreateInVisibleWindow(shcHookWndClass, HookProc);
end;
procedure TSysHook.HookProc(var Msg: TMessage); //if we make a break point here - hooked window hangs!
begin
case Msg.Msg of
WM_KEYHOOK: DoOnKeyDown(Msg);
WM_EXKEYHOOK: DoOnExKeyDown(Msg);
else
Msg.Result := DefWindowProc(FWindowHandle, Msg.Msg, Msg.WParam,
Msg.LParam);
end;
end;
...