Windows全球键盘钩 - Delphi [英] Windows Global Keyboard Hook - Delphi
问题描述
我已经使用互联网上的源代码创建了一个GLOBAL键盘挂钩DLL。除了浏览器之外,除了浏览器之外,它最好的部分是非常出色的。除非浏览器重点关注,否则浏览器中的每个键都会被选中。失去按下的第一个键。在IE和Firefox中测试过,并且似乎都是一样的。
例如,如果我打开IE并开始输入www。 ,我只能回来了。如果浏览器窗口保持焦点,则不会再丢失任何键。一旦浏览器失去了重点并重新获得关注,第一个键就会再次出现。
可能是因为仅使用WH_KEYDOWN而不是WH_KEYPRESS / WH_KEYUP?任何人都可以这样做吗?
谢谢
PS:钩子功能本身如下:该DLL发送了一个备忘录框和应用程序句柄,DLL将发送消息以及一个usermessage。
function KeyHookFunc Code,VirtualKey,KeyStroke:Integer):LRESULT;标准
var
KeyState1:TKeyBoardState;
AryChar:数组[0..1]的Char;
计数:整数;
begin
结果:= 0;
如果Code = HC_NOREMOVE然后退出;
结果:= CallNextHookEx(hKeyHook,Code,VirtualKey,KeyStroke);
{我把CallNextHookEx移到这里,但如果你想阻止
或更改任何键,然后将其移回}
如果Code< 0然后
退出;
如果代码= HC_ACTION然后
开始
如果((KeyStroke和(1 shl 30)))0然后
如果不是IsWindow(hMemo)然后
开始
{我把OpenFileMapping移到这里,所以它不会被打开
,除非应用程序的DLL被附加到获取一些关键消息}
hMemFile:= OpenFileMapping(FILE_MAP_WRITE,False, NetParentMAP'); // Global7v9k
PHookRec1:= MapViewOfFile(hMemFile,FILE_MAP_WRITE,0,0,0);
如果PHookRec1<>然后
开始
hMemo:= PHookRec1.MemoHnd;
hApp:= PHookRec1.AppHnd;
结束
结束
if((KeyStroke AND(1 shl 31))= 0)then // if((KeyStroke and(1 shl 30))<> 0)then
begin
GetKeyboardState KeyState1);
计数:= ToAscii(VirtualKey,KeyStroke,KeyState1,AryChar,0);
如果Count = 1然后
begin
SendMessage(hMemo,WM_CHAR,Ord(AryChar [0]),0);
{我包括2种方式获得Charaters,一个Memo Hnadle和
a WM_USER + 1678消息给程序}
PostMessage(hApp,WM_USER + 1678,Ord(AryChar [0]), 0);
结束
结束
结束
结束
您没有分配您的 hMemo
和 hApp
值早。您正在等待,直到具有1的先前状态标志的通知,这表示一个键已被按下至少1次重复计数,或正在被释放,以先到者为准。因此,当您的钩子检测到第一个按键通知时, hMemo
和 hApp
不可用。这就是为什么你错过角色。尝试这样做:
function KeyHookFunc(Code,VirtualKey,KeyStroke:Integer):LRESULT;标准
var
KeyState1:TKeyBoardState;
AryChar:数组[0..1]的Char;
计数:整数;
begin
结果:= CallNextHookEx(hKeyHook,Code,VirtualKey,KeyStroke);
如果Code<> HC_ACTION然后退出;
{一个密钥通知发生,在检查实际的密钥状态之前准备HWNDs
}
if(hMemo = 0)或(hApp = 0)然后
开始
如果hMemFile = 0然后
开始
hMemFile:= OpenFileMapping(FILE_MAP_WRITE,False,'NetParentMAP');
如果hMemFile = 0然后退出;
结束
如果PHookRec1 = nil然后
begin
PHookRec1:= MapViewOfFile(hMemFile,FILE_MAP_WRITE,0,0,0);
如果PHookRec1 = nil然后退出;
结束
hMemo:= PHookRec1.MemoHnd;
hApp:= PHookRec1.AppHnd;
如果(hMemo = 0)和(hApp = 0)则退出;
结束
if((KeyStroke and(1 shl 31))= 0)then // a key is down
begin
GetKeyboardState(KeyState1);
计数:= ToAscii(VirtualKey,KeyStroke,KeyState1,AryChar,0);
如果Count = 1则
begin
如果hMemo<> 0 then SendMessage(hMemo,WM_CHAR,Ord(AryChar [0]),0);
如果hApp<> 0 then PostMessage(hApp,WM_USER + 1678,Ord(AryChar [0]),0);
结束
结束
结束
I've created a GLOBAL keyboard hook DLL, using source code found on the internet. For the best part it works brilliant, except when it comes to browsers.
It picks up every key in the browser except, it seems, when the browser gets focus, it looses the first key that is pressed. Tested this in IE and Firefox and it seems to be the same for both.
For instance, if I open IE and start typing www. , I only get back ww. If the browser window stays in focus no further keys are lost. As soon as the browser looses focus and regains focus, the first key is again missing.
Could it be because of using only WH_KEYDOWN instead of WH_KEYPRESS / WH_KEYUP ? Can anyone shed some light on this please?
Thank you
PS: The hook function itself is below: The DLL is sent a memo box and app handle to wich the DLL will send messages as well as a 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;
You are not assigning your hMemo
and hApp
values early enough. You are waiting until a notification with a "previous state" flag of 1, which indicates a key has been held down for at least 1 repeat count, or is being released, whichever occurs first. Thus, hMemo
and hApp
are not available yet when your hook detects its first key down notification. That is why you miss characters. Try this 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;
这篇关于Windows全球键盘钩 - Delphi的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!