Я создал ГЛОБАЛЬНЫЙ захват клавиатуры DLL, с помощью исходного кода, найденного в Интернете. Для большой части это работает блестящее, кроме тех случаев, когда это прибывает в браузеры.
Это берет каждый ключ в браузере кроме, кажется, когда браузер получает фокус, это освобождает первую клавишу, которая нажата. Протестированный это в IE и Firefox и это, кажется, то же для обоих.
Например, если я открываю IE и начинаю вводить www., я только возвращаю ww. Если окно браузера остается в фокусе, никакие дальнейшие ключи не потеряны. Как только браузер освобождает фокус и возвращает фокус, первый ключ снова отсутствует.
Это могло быть из-за использования только WH_KEYDOWN вместо WH_KEYPRESS / WH_KEYUP? Кто-либо может пролить некоторый свет на это?
Спасибо
PS: сама функция рычага ниже: DLL отправляется поле заметки и дескриптор приложения, в который DLL отправит сообщения, а также usermessage.
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;
Вы не назначаете свой 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;