我使用互联网上的源代码创建了一个GLOBAL键盘钩子DLL.最好的部分是它非常出色,除了它涉及到浏览器.
它会接收浏览器中的每个键,除了看起来,当浏览器获得焦点时,它会丢失按下的第一个键.在IE和Firefox中进行了测试,两者似乎都是一样的.
例如,如果我打开IE并开始输入www.,我只回来了.如果浏览器窗口保持清晰,则不会丢失其他密钥.一旦浏览器失去焦点并重新获得焦点,第一个键就会再次丢失.
可能是因为只使用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,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); 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,0); end; end; end; end;
您没有及早分配hMemo和hApp值.您正在等待“先前状态”标志为1的通知,该通知表示某个键已被按下至少1次重复计数,或者正在被释放,以先发生者为准.因此,当您的挂钩检测到其第一个按键通知时,hMemo和hApp尚不可用.这就是你错过角色的原因.试试这个:
function KeyHookFunc(Code,KeyStroke: Integer): LRESULT; stdcall; var KeyState1: TKeyBoardState; AryChar: array[0..1] of Char; Count: Integer; begin Result := CallNextHookEx(hKeyHook,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,'NetParentMAP'); if hMemFile = 0 then Exit; end; if PHookRec1 = nil then begin PHookRec1 := MapViewOfFile(hMemFile,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,0); if Count = 1 then begin if hMemo <> 0 then SendMessage(hMemo,0); if hApp <> 0 then PostMessage(hApp,0); end; end; end;