2010-07-01 47 views
6

J'ai créé une DLL de hook clavier GLOBAL, en utilisant le code source trouvé sur Internet. Pour le meilleur, cela fonctionne brillamment, sauf quand il s'agit de navigateurs.Windows Global Keyboard Hook - Delphi

Il prend toutes les clés dans le navigateur, sauf, semble-t-il, quand le navigateur obtient le focus, il perd la première touche qui est pressée. Testé dans IE et Firefox et il semble être le même pour les deux. Par exemple, si j'ouvre IE et commence à taper www. , Je reviens seulement ww. Si la fenêtre du navigateur reste active, aucune autre touche n'est perdue. Dès que le navigateur perd le focus et reprend le focus, la première touche est à nouveau manquante. Est-ce dû à l'utilisation de seulement WH_KEYDOWN au lieu de WH_KEYPRESS/WH_KEYUP?

Quelqu'un peut-il nous éclairer?

Merci

PS: La fonction crochet lui-même est ci-dessous: La DLL est envoyé une boîte mémo et poignée app pour la DLL wich va envoyer des messages ainsi qu'un 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; 
+2

Un échantillon de votre code aide beaucoup les personnes qui essaient de répondre à votre code. –

+0

Oui je sais, le problème est que je devrai mettre en place l'ensemble du projet car je ne sais pas où le problème pourrait être. Ce que je peux dire est que j'utilise ce qui suit pour définir le crochet: hKeyHook: = SetWindowsHookEx (WH_KEYBOARD, KeyHookFunc, hInstance, 0); Mais j'ai vu un projet C# qui semble utiliser le WH_KEYBOARD_LL, cela pourrait-il faire une différence? – Paul

+0

Au moins vous pourriez nous montrer la source que vous avez trouvée sur Internet. Peut-être que ce code n'est pas correct ... – bepe4711

Répondre

8

Vous n'êtes pas assignez vos hMemo et hApp valeurs assez tôt. Vous attendez une notification avec un indicateur "état précédent" de 1, qui indique qu'une touche a été maintenue enfoncée pendant au moins 1 répétition, ou est en cours de relâchement, selon la première éventualité. Par conséquent, les codes hMemo et hApp ne sont pas encore disponibles lorsque votre hook détecte sa première notification. C'est pourquoi vous manquez des caractères. Essayez ceci à la place:

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; 
+3

mec vous êtes une star. erreur probablement stupide, mais néanmoins. Je vous remercie – Paul