2009-02-08 12 views
5

Estoy tratando de escribir una aplicación que responde cada vez que se presiona la tecla Shift, sin importar qué aplicación tenga actualmente el foco.¿Responder al teclado cuando no está enfocado? (C#, Vista)

Intenté esto con SetWindowsHookEx() y con GetKeyboardState(), pero ambos solo funcionan cuando la ventana de la aplicación tiene foco. Necesito que funcione globalmente.

¿Cómo puedo hacer esto?

Respuesta

5

Ninguna de las respuestas proporcionadas me ayudó a resolver mi problema, pero yo mismo encontré la respuesta. Aquí está.

El uso de SetWindowsHookEx() con WH_KEYBOARD_LL fue el enfoque correcto. Sin embargo, los otros parámetros a SetWindowsHookEx() son poco intuitivo:

  • El último parámetro, dwThreadId, tiene que ser 0.
  • La segunda último parámetro, hMod, necesita para que apunte a algunos DLL. Usé User32, que es una DLL que siempre se carga de todos modos y es utilizada por todos los procesos con una GUI. Obtuve esta idea desde a CodeProject post about this.

De este modo, el código se ve un poco como esto:

instance = LoadLibrary("User32"); 
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, hookFunction, instance, 0); 

La documentación es clara la segunda último parámetro. Dice:

El parámetro hMod debe establecerse en NULL [...] si el procedimiento de enlace está dentro del código asociado con el proceso actual.

No indica que esto sólo se aplica a algunos tipos de ganchos, pero no a WH_KEYBOARD_LL y WH_MOUSE_LL.

+0

Sí, es lo que quieren decir - para un gancho de ratón de bajo nivel o el teclado (o cualquier otro gancho local) HMOD debe ser IntPtr.Zero. –

+0

Hmmm, dices que las otras publicaciones no fueron útiles, luego procede a publicar la misma respuesta que nobugz ya proporcionó y marca la tuya como la respuesta correcta. –

+0

Nobugz no dice qué hacer con hMod en absoluto, y, contrariamente a su primer comentario, esta respuesta sugiere que hMod se establezca en algo ** diferente ** a IntPtr.Zero. –

5

Vas a tener que utilizar SetWindowsHookEx(). Solo hay dos tipos de enlaces que puede implementar en un lenguaje administrado, WH_KEYBOARD_LL y WH_MOUSE_LL. Todos los otros ganchos requieren una DLL que se puede inyectar en otro proceso. Las DLL administradas no pueden ser inyectadas, la CLR no se puede inicializar.

Este blog post tiene un ejemplo funcional.

+0

La mayoría de los otros ganchos también se pueden implementar en un lenguaje administrado, pero solo si están restringidos a los hilos del proceso actual. Los ganchos de bajo nivel para mouse y teclado son los únicos ganchos 'globales' permitidos. –

+0

Esto solo roza la superficie del problema y realmente no entra en ningún nivel de profundidad. –

+1

Esta es una respuesta muy específica a la pregunta específica. Es un poco corto y pasa por alto cierta información por simplicidad, pero contiene toda la información que necesitaría un desarrollador de software competente. –

2

Si utiliza la técnica en la publicación a la que hace referencia nobugz, deberá asegurarse de que el delegado no se recoja basura, p. utilizando GC.KeepAlive (_proc) al establecer el gancho, de lo contrario, después de un período indeterminado, el gancho dejará de funcionar cuando el delagate reciba GC.

Cuestiones relacionadas