Windows Global Keyboard Hook - Delphi - PullRequest
       34

Windows Global Keyboard Hook - Delphi

6 голосов
/ 01 июля 2010

Я создал GLOBAL DLL-библиотеку хуков клавиатуры, используя исходный код, найденный в Интернете.В лучшем случае он работает великолепно, за исключением тех случаев, когда речь идет о браузерах.

Он подхватывает каждую клавишу в браузере, за исключением того, что, кажется, когда браузер получает фокус, он теряет первую нажатую клавишу.Протестировал это в IE и Firefox, и похоже, что они одинаковы.

Например, если я открою IE и начну вводить www.Я только вернусь WW.Если окно браузера остается в фокусе, дальнейшие ключи не теряются.Как только браузер теряет фокус и восстанавливает фокус, снова исчезает первый ключ.

Может ли это быть из-за использования только WH_KEYDOWN вместо WH_KEYPRESS / WH_KEYUP?Может кто-нибудь пролить свет на это, пожалуйста?

Спасибо

PS: Сама функция ловушки находится ниже: DLL отправляется блокнот и дескриптор приложения, в который DLL будет отправлять сообщения кака также пользовательское сообщение.

    function KeyHookFunc(Code, VirtualKey, KeyStroke: Integer): LRESULT; stdcall; 
var
  KeyState1: TKeyBoardState; 
  AryChar: array[0..1] of Char; 
  Count: Integer; 
begin 
  Result := 0; 
  if Code = HC_NOREMOVE then Exit;

  Result := CallNextHookEx(hKeyHook, Code, VirtualKey, KeyStroke); 
  {I moved the CallNextHookEx up here but if you want to block 
   or change any keys then move it back down} 
  if Code < 0 then 
    Exit; 
  if Code = HC_ACTION then 
  begin 
    if ((KeyStroke and (1 shl 30)) <> 0) then 
      if not IsWindow(hMemo) then
      begin 
       {I moved the OpenFileMapping up here so it would not be opened 
        unless the app the DLL is attatched to gets some Key messages} 
        hMemFile  := OpenFileMapping(FILE_MAP_WRITE, False, 'NetParentMAP');//Global7v9k
        PHookRec1 := MapViewOfFile(hMemFile, FILE_MAP_WRITE, 0, 0, 0); 
        if PHookRec1 <> nil then 
        begin 
          hMemo := PHookRec1.MemoHnd; 
          hApp  := PHookRec1.AppHnd; 
        end; 
      end;
    if ((KeyStroke AND (1 shl 31))  = 0) then //if ((KeyStroke and (1 shl 30)) <> 0) then
    begin 
      GetKeyboardState(KeyState1); 
      Count := ToAscii(VirtualKey, KeyStroke, KeyState1, AryChar, 0); 
      if Count = 1 then
      begin
        SendMessage(hMemo, WM_CHAR, Ord(AryChar[0]), 0); 
        {I included 2 ways to get the Charaters, a Memo Hnadle and 
         a WM_USER+1678 message to the program} 
        PostMessage(hApp, WM_USER + 1678, Ord(AryChar[0]), 0);
      end;
    end; 
  end; 
end; 

1 Ответ

8 голосов
/ 02 июля 2010

Вы не назначаете значения hMemo и hApp достаточно рано. Вы ожидаете, пока уведомление с флагом «предыдущего состояния», равным 1, указывает на то, что клавиша удерживалась как минимум в течение 1 повторного счета или освобождается, в зависимости от того, что произойдет раньше. Таким образом, hMemo и hApp еще не доступны, когда ваша ловушка обнаруживает свое первое уведомление о нажатии клавиши. Вот почему вы скучаете по персонажам. Попробуйте вместо этого:

function KeyHookFunc(Code, VirtualKey, KeyStroke: Integer): LRESULT; stdcall;
var
  KeyState1: TKeyBoardState;
  AryChar: array[0..1] of Char;
  Count: Integer;
begin
  Result := CallNextHookEx(hKeyHook, Code, VirtualKey, KeyStroke);
  if Code <> HC_ACTION then Exit;

  { a key notification had occured, prepare the HWNDs
  before checking the actual key state }
  if (hMemo = 0) or (hApp = 0) then
  begin
    if hMemFile = 0 then
    begin
      hMemFile := OpenFileMapping(FILE_MAP_WRITE, False, 'NetParentMAP');
      if hMemFile = 0 then Exit;
    end;
    if PHookRec1 = nil then
    begin
      PHookRec1 := MapViewOfFile(hMemFile, FILE_MAP_WRITE, 0, 0, 0);
      if PHookRec1 = nil then Exit;
    end;
    hMemo := PHookRec1.MemoHnd;
    hApp  := PHookRec1.AppHnd;
    if (hMemo = 0) and (hApp = 0) then Exit;
  end;

  if ((KeyStroke and (1 shl 31)) = 0) then // a key is down
  begin
    GetKeyboardState(KeyState1);
    Count := ToAscii(VirtualKey, KeyStroke, KeyState1, AryChar, 0);
    if Count = 1 then
    begin
      if hMemo <> 0 then SendMessage(hMemo, WM_CHAR, Ord(AryChar[0]), 0);
      if hApp <> 0 then PostMessage(hApp, WM_USER + 1678, Ord(AryChar[0]), 0);
    end;
  end;
end;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...