键盘钩冻结钩子应用程序

时间:2017-05-19 16:56:22

标签: delphi winapi hook

使用典型的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;
...

0 个答案:

没有答案