2010-07-01 29 views
6

He creado una DLL de gancho de teclado GLOBAL, utilizando el código fuente que se encuentra en Internet. Para la mejor parte, funciona genial, excepto cuando se trata de navegadores.Windows Global Keyboard Hook - Delphi

Captura todas las teclas del navegador excepto que, al parecer, cuando el navegador obtiene el foco, pierde la primera tecla que se presiona. Probado esto en IE y Firefox y parece ser el mismo para ambos.

Por ejemplo, si abro IE y comienzo a escribir www. , Solo vuelvo, ww. Si la ventana del navegador permanece enfocada, no se pierden más teclas. Tan pronto como el navegador pierde el foco y recupera el foco, la primera clave vuelve a faltar.

¿Podría ser por usar solo WH_KEYDOWN en lugar de WH_KEYPRESS/WH_KEYUP? ¿Alguien puede arrojar algo de luz sobre esto, por favor?

Gracias

PS: La función de enlace en sí es el siguiente: El archivo DLL se envía una caja de notas y el mango de aplicación para wich la DLL enviará mensajes, así como 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

Una muestra de su código ayuda mucho a las personas que intentan contestar su código. –

+0

Sí, lo sé, el problema es que tendré que poner todo el proyecto, ya que no sé dónde podría estar el problema. Lo que puedo decir es que utilizo el siguiente para establecer el enlace: hKeyHook: = SetWindowsHookEx (WH_KEYBOARD, KeyHookFunc, hInstance, 0); Pero he visto un proyecto de C# que parece usar WH_KEYBOARD_LL, ¿podría eso hacer la diferencia? – Paul

+0

Al menos podría mostrarnos la fuente que ha encontrado en Internet. Tal vez este código no es correcto ... – bepe4711

Respuesta

8

No está asignando sus hMemo y hApp valores suficientemente temprano. Está esperando hasta recibir una notificación con un indicador de "estado anterior" de 1, que indica que se mantuvo presionada una tecla durante al menos 1 conteo de repetición, o se está liberando, lo que ocurra primero. Por lo tanto, hMemo y hApp aún no están disponibles cuando su gancho detecta su primera notificación de desactivación de la tecla. Es por eso que extrañas personajes. Pruebe esto en su lugar:

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

amigo eres una estrella. probablemente un error estúpido, pero no obstante. Gracias – Paul