2010-07-01 6 views
6

Ich habe eine GLOBAL Tastatur Hook DLL erstellt, mit Quellcode im Internet gefunden. Für den besten Teil funktioniert es hervorragend, außer wenn es um Browser geht.Windows Global Keyboard Hook - Delphi

Es nimmt jeden Schlüssel im Browser auf, außer es scheint, wenn der Browser den Fokus erhält, verliert er die erste Taste, die gedrückt wird. Getestet dies in IE und Firefox und es scheint für beide gleich zu sein.

Zum Beispiel, wenn ich IE öffne und mit der Eingabe www. Ich komme nur zurück. Bleibt das Browserfenster im Fokus, gehen keine weiteren Tasten verloren. Sobald der Browser den Fokus verliert und wieder fokussiert, fehlt der erste Schlüssel wieder.

Könnte es daran liegen, dass nur WH_KEYDOWN anstelle von WH_KEYPRESS/WH_KEYUP verwendet wird? Kann jemand bitte etwas Licht darauf werfen?

Danke

PS: Die Hook-Funktion selbst ist unten: Die DLL eine Memo-Box und App Griff, um die DLL-Nachrichten sowie eine usermessage an weicht geschickt senden.

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

Ein Beispiel Ihres Codes hilft viel für Leute, die versuchen, Ihren Code zu beantworten. –

+0

Ja, ich weiß, das Problem ist, dass ich das ganze Projekt aufstellen muss, da ich nicht weiß, wo das Problem liegen könnte. Was ich sagen kann ist, dass ich den folgenden Befehl verwende, um den Hook zu setzen: hKeyHook: = SetWindowsHookEx (WH_KEYBOARD, KeyHookFunc, hInstance, 0); Aber ich habe ein C# -Projekt gesehen, das WH_KEYBOARD_LL zu verwenden scheint. Könnte das einen Unterschied machen? – Paul

+0

Zumindest könnten Sie uns die Quelle zeigen, die Sie im Internet gefunden haben. Vielleicht ist dieser Code nicht korrekt ... – bepe4711

Antwort

8

Sie zuweisen nicht Ihre hMemo und hApp früh genug Werte. Sie warten auf eine Benachrichtigung mit einem "vorherigen Zustand" -Flag von 1, die anzeigt, dass eine Taste für mindestens 1 Wiederholungszählung gedrückt wurde oder freigegeben wird, je nachdem, was zuerst eintritt. Daher sind hMemo und hApp noch nicht verfügbar, wenn Ihr Hook die erste Schlüssel-Down-Benachrichtigung erkennt. Deshalb vermisst du Charaktere. Versuchen Sie dies stattdessen:

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

Kumpel, du bist ein Star. wahrscheinlich ein dummer Fehler, aber nichtsdestoweniger. Vielen Dank – Paul