2012-05-07 18 views
5

¿Qué tengo que usar para poder obtener "todas las teclas" que se presionan en el teclado en este momento? Desde Form.KeyPress += new EventHandler() no hace mucho cuando está lleno de controles. No lo llama, no importa lo que haga, ni KeyDown, KeyUp o cualquier otra cosa ... y sí, sé cómo usarlos.Obtener todas las teclas que se presionan

Por lo tanto, si hay alguna función en el sistema que pueda verificar si hay teclas presionadas, que devuelve una matriz de las teclas utilizadas o algo así, agradecería que me señalara en la dirección correcta.

+1

¿Desea que se presionen todas las teclas cuando ejecuta una pieza específica de código, o desea un evento que ocurre cada vez que se presiona una tecla? – zimdanen

+0

posible duplicado de [¿La mejor forma de implementar accesos directos de teclado en winforms?] (Http://stackoverflow.com/questions/400113/best-way-to-implement-keyboard-shortcuts-in-winforms) –

+0

Digamos que quiero tener un controlador de eventos para MouseWheel, pero quiero que se presione la tecla "Ctrl" cuando ejecuto algo en el EventHandler. así que si muevo la rueda solo obtengo los resultados de la rueda del mouse, no la de la tecla. – Deukalion

Respuesta

12

Parece que desea consultar el estado de todas las teclas del teclado. La mejor función para la que es el Win32 API llamada GetKeyboardState

No creo que hay una buena equivalente logrado de esa función. El código PInvoke porque es bastante sencillo

[DllImport("user32.dll")] 
[return: MarshalAs(UnmanagedType.Bool)] 
static extern bool GetKeyboardState(byte [] lpKeyState); 

var array = new byte[256]; 
GetKeyboardState(array); 

Esto rellenará el byte[] con las flechas arriba/abajo estado de cada tecla virtual en el sistema. Si se establece el bit alto, entonces la tecla virtual está actualmente presionada. La asignación de un Key a un código de clave virtual se realiza considerando únicamente la parte byte del valor numérico Key.

public static byte GetVirtualKeyCode(Key key) { 
    int value = (int)key; 
    return (byte)(value & 0xFF); 
} 

Los trabajos anteriores para la mayoría de los valores Key pero hay que tener cuidado con las teclas modificadoras. Los valores Keys.Alt, Keys.Control y Keys.Shift no funcionarán aquí porque técnicamente son modificadores y no valores clave. Para utilizar modificadores es necesario utilizar los valores de las claves asociadas reales Keys.ControlKey, Keys.LShiftKey, etc ... (en realidad cualquier cosa que termina con llave)

lo que comprobar si una clave particular, se establece que se puede hacer de la siguiente manera

var code = GetVirtualKeyCode(Key.A); 
if ((array[code] & 0x80) != 0) { 
    // It's pressed 
} else { 
    // It's not pressed 
} 
+0

También funciona para las teclas modificadoras; sin embargo, debe utilizar las teclas Keys.AltKey, ShiftKey y ControlKey. –

+0

@HansPassant buena llamada, se olvidó de esas entradas – JaredPar

+0

Sí ... Pero alguien que no ha usado esas cosas antes podría ser bueno incluir qué espacios de nombres necesito, por qué DllImport se muestra en rojo, por qué GetKeyboardState no está en ninguna parte. , etc, etc ... La mitad de las respuestas al horno significa que tengo que buscar más respuestas igual a ninguna respuesta. – Deukalion

0

Creo que está buscando el evento PreviewKeyDown que se activará si se presiona una tecla mientras el formulario tiene foco, incluso si otro control secundario dentro de ese formulario tiene actualmente el foco.

1

Si solo necesita saber todas las teclas cuando su aplicación está activa, independientemente de qué control dentro de su aplicación tenga el foco, entonces puede usar la propiedad KeyPreview de su formulario.

Simplemente establezca la propiedad en verdadero y suscríbase a los eventos clave deseados en el formulario. Ahora recibirá todas las pulsaciones de teclas dentro de su aplicación antes de que se desvíen al control concreto, lo que le permite reaccionar y cancelar su reenvío al control estableciendo la propiedad Cancel en verdadero.

Si necesita recibir las teclas presionadas mientras su aplicación no es la activa, entonces necesita algún tipo de gancho de teclado de bajo nivel. No lo probé, pero this article on CodeProject parece bastante prometedor para este caso.

3

He ampliado un poco la respuesta de JaredPar.El siguiente método devuelve la colección de todas las teclas que se están presionando actualmente:

using System.Collections.Generic; 
using System.Linq; 
using System.Runtime.InteropServices; 
using System.Windows.Input; 

private static readonly byte[] DistinctVirtualKeys = Enumerable 
    .Range(0, 256) 
    .Select(KeyInterop.KeyFromVirtualKey) 
    .Where(item => item != Key.None) 
    .Distinct() 
    .Select(item => (byte)KeyInterop.VirtualKeyFromKey(item)) 
    .ToArray(); 

/// <summary> 
/// Gets all keys that are currently in the down state. 
/// </summary> 
/// <returns> 
/// A collection of all keys that are currently in the down state. 
/// </returns> 
public IEnumerable<Key> GetDownKeys() 
{ 
    var keyboardState = new byte[256]; 
    GetKeyboardState(keyboardState); 

    var downKeys = new List<Key>(); 
    for (var index = 0; index < DistinctVirtualKeys.Length; index++) 
    { 
     var virtualKey = DistinctVirtualKeys[index]; 
     if ((keyboardState[virtualKey] & 0x80) != 0) 
     { 
      downKeys.Add(KeyInterop.KeyFromVirtualKey(virtualKey)); 
     } 
    } 

    return downKeys; 
} 

[DllImport("user32.dll")] 
[return: MarshalAs(UnmanagedType.Bool)] 
private static extern bool GetKeyboardState(byte[] keyState); 
+0

Me cuesta mucho traducir la asignación 'DistinctVirtualKeys' en VB.Net. ¿Puedes comentarlo mejor y también me da error de que no hay ningún parámetro para '.Select (KeyInterop.KeyFromVirtualKey)'? – beppe9000

Cuestiones relacionadas