Windows Global Keyboard Hook - Delphi

I created a DLL with a GLOBAL keyboard using the source code found on the Internet. At best, it works brilliantly, except when it comes to browsers.

It takes every key in the browser, except that when the browser gains focus, it loses the first key pressed. This is tested in IE and Firefox, and it seems they are the same for both.

For example, if I open IE and start typing www., I will just return ww. If the browser window remains in focus, further keys are not lost. As soon as the browser loses focus and restores focus, the first key is again absent.

Could this be due to using only WH_KEYDOWN instead of WH_KEYPRESS / WH_KEYUP? Can someone shed some light on this, please?

thanks

PS: the hook: DLL function itself is sent a memo block and an application descriptor to which the DLL will send messages, as well as 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; 
+6
delphi keyboard-hook setwindowshookex
source share
1 answer

You do not assign your hMemo and hApp values โ€‹โ€‹early enough. You expect a notification with the โ€œprevious stateโ€ flag equal to 1, which indicates that the key is held for at least 1 repetition or is released, whichever occurs first. Thus, hMemo and hApp are not yet available when your hook detects its first notification of a keystroke. That's why you skip characters. Try instead:

 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; 
+8
source share

All Articles