2009-07-21 16 views
9

P. ej. con winamp (al menos en Windows), puede reproducir un juego de pantalla completa con winamp en segundo plano y usar los botones multimedia * para controlar el sonido. Winamp no necesita enfocarse, permitiendo que el juego continúe en pantalla completa.Captura de teclas sin foco

Preferiría escribir esto en Java, pero probablemente eso no vaya a funcionar (la captura de teclas sin foco ya es difícil en Java afaik), por lo que cualquier solución de C# también está bien.

Entonces la pregunta básica es: ¿cómo capturar las pulsaciones de teclas sin foco?

*) Creo que los botones 'back/forward/stop/mail/search/favorites/web/home' se llaman botones multimedia, pero un nombre mejor sería bienvenido :).

+0

yo los medios de comunicación botones o teclas multimedia llamo también, no saber un nombre mejor – Luc

Respuesta

7

ganchos de ventana de bajo nivel es una forma de hacerlo. Aquí hay uno article y aquí hay un poco más de información de MSDN.

Ésta es una vista parcial de lo que el código puede verse como:

private IntPtr LowLevelKeyboardHook(int nCode, WindowsMessages wParam, [In] KBDLLHOOKSTRUCT lParam) 
    { 
     bool callNext = true; 

     bool isKeyDown = (wParam == WindowsMessages.KEYDOWN || wParam == WindowsMessages.SYSKEYDOWN); 
     bool isKeyUp = (wParam == WindowsMessages.KEYUP || wParam == WindowsMessages.SYSKEYUP); 

     if ((nCode >= 0) && (isKeyDown || isKeyUp)) 
     { 
      // the virtual key codes and the winforms Keys have the same enumeration 
      // so we can freely cast back and forth between them 
      Keys key = (Keys)lParam.vkCode; 

      // Do your other processing here... 
     } 

     // if any handler returned false, trap the message 
     return (callNext) ? User32.CallNextHookEx(_mainHook, nCode, wParam, lParam) : _nullNext; 
    } 


    /// <summary> 
    /// Registers the user's LowLevelKeyboardProc with the system in order to 
    /// intercept any keyboard events before processed in the regular fashion. 
    /// This can be used to log all keyboard events or ignore them. 
    /// </summary> 
    /// <param name="hook">Callback function to call whenever a keyboard event occurs.</param> 
    /// <returns>The IntPtr assigned by the Windows's sytem that defines the callback.</returns> 
    private IntPtr RegisterLowLevelHook(LowLevelKeyboardProc hook) 
    { 
     IntPtr handle = IntPtr.Zero; 

     using (Process currentProcess = Process.GetCurrentProcess()) 
     using (ProcessModule currentModule = currentProcess.MainModule) 
     { 
      IntPtr module = Kernel32.GetModuleHandle(currentModule.ModuleName); 
      handle = User32.SetWindowsHookEx(HookType.KEYBOARD_LL, hook, module, 0); 
     } 

     return handle; 
    } 

    /// <summary> 
    /// Unregisters a previously registered callback from the low-level chain. 
    /// </summary> 
    /// <param name="hook">IntPtr previously assigned to the low-level chain. 
    /// Users should have stored the value given by 
    /// <see cref="Drs.Interop.Win32.LowLevelKeyboard.RegisterLowLevelHook"/>, 
    /// and use that value as the parameter into this function.</param> 
    /// <returns>True if the hook was removed, false otherwise.</returns> 
    private bool UnregisterLowLevelHook(IntPtr hook) 
    { 
     return User32.UnhookWindowsHookEx(hook); 
    } 

Sólo en práctica todos los P/Invoke declaraciones necesario, y debería funcionar. Uso este enfoque en mi aplicación y funciona bien.

+0

Esos tipos no son reconocidos en mi aplicación y no compila (WindowsMessages, User32, etc.) ¿Qué hiciste para que funcione? ¿tiene este código en línea en cualquier lugar por casualidad? –

+1

No, esas son las declaraciones que necesitaría declarar. No tengo ese código en línea, pero puedes crear stubs simples usando las firmas P/Invoke de http://www.pinvoke.net. –

+0

¿qué es la variable _nullNext? –

Cuestiones relacionadas