2012-05-07 15 views
5

Cosa devo usare per essere in grado di ottenere "tutti i tasti" che vengono premuti sulla tastiera al momento? Dal momento che Form.KeyPress += new EventHandler() non fa molto quando è pieno di controlli. Non lo chiama, non importa quello che faccio, né KeyDown, KeyUp o qualsiasi altra cosa ... e sì, so come usarli.Ricevi tutti i tasti che vengono premuti

Quindi, se nel sistema è presente una funzione in grado di verificare la presenza di tasti premuti, che restituisce un array di chiavi utilizzate o qualcosa del genere, sarei grato di essere indirizzato nella giusta direzione.

+1

Vuoi tutti i tasti premuti quando si esegue una parte specifica di codice, o volete un evento che accade ogni volta che si preme un tasto? – zimdanen

+0

possibile duplicato di [Il modo migliore per implementare le scorciatoie da tastiera in winforms?] (Http://stackoverflow.com/questions/400113/best-way-to-implement-keyboard-shortcuts-in-winforms) –

+0

Dire che voglio avere un eventhandler per MouseWheel, ma voglio che venga premuto il tasto "Ctrl" quando eseguo qualcosa nell'EventHandler. quindi, se faccio scorrere la ruota, ottengo solo i risultati della rotellina del mouse, non la pressione del tasto. – Deukalion

risposta

12

Sembra che si voglia interrogare lo stato di tutti i tasti della tastiera. La funzione migliore di ciò è l'API Win32 chiamata GetKeyboardState

Io non credo che ci sia un buon equivalente gestito di quella funzione. Il codice PInvoke perché è abbastanza semplice

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

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

Questo popolerà la byte[] con l'alto/basso stato di ogni tasto virtuale nel sistema. Se il bit più alto è impostato, al momento viene premuto il tasto virtuale. La mappatura di un Key a un codice di chiave virtuale viene eseguita considerando solo la parte byte del valore numerico Key.

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

I lavori di cui sopra per la maggior parte dei valori Key ma è necessario stare attenti con tasti modificatori. I valori Keys.Alt, Keys.Control e Keys.Shift non funzioneranno qui perché sono tecnicamente modificatori e non valori chiave. Per utilizzare modificatori è necessario utilizzare l'attuale valori chiave associati Keys.ControlKey, Keys.LShiftKey, ecc ... (davvero nulla che si conclude con la chiave)

Quindi verificare se un determinato tasto è impostata può essere fatto come segue

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

Funziona anche con i tasti di modifica, tuttavia è necessario utilizzare Keys.AltKey, ShiftKey e ControlKey. –

+0

@HansPassant buona chiamata, ho dimenticato quelle voci – JaredPar

+0

Sì ... Ma uno che non ha usato quelle cose prima potrebbe essere bello includere gli spazi dei nomi di cui ho bisogno, perché DllImport mostra il rosso, perché GetKeyboardState non è in nessun posto da trovare , ecc. ecc ... Le risposte a metà forno significa che devo cercare di più per le risposte è uguale a nessuna risposta. – Deukalion

0

Credo che stiate cercando l'evento PreviewKeyDown che si attiva se viene premuto un tasto mentre il modulo è attivo, anche se al momento è attivo un altro controllo figlio all'interno di tale modulo.

1

Se è necessario conoscere tutte le sequenze di tasti quando l'applicazione è attiva, indipendentemente dal controllo all'interno dell'applicazione, è possibile utilizzare la proprietà KeyPreview del modulo.

Impostare semplicemente la proprietà su true e sottoscrivere gli eventi chiave desiderati nel modulo. Ora riceverai tutte le sequenze di tasti all'interno della tua applicazione prima che vengano inoltrate al controllo concreto, permettendoti di reagire su di te e annullare l'inoltro al controllo impostando la proprietà Cancel su true.

Se è necessario ricevere i tasti premuti mentre l'applicazione non è attiva, è necessario un gancio per tastiera di basso livello. Non l'ho provato, ma il this article on CodeProject sembra abbastanza promettente per questo caso.

3

Ho ampliato la risposta di JaredPar un po '.Il seguente metodo restituisce l'insieme di tutte le chiavi che sono attualmente in fase di pressione:

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

Ho difficoltà a tradurre l'assegnazione di 'DistinctVirtualKeys' in VB.Net. Puoi commentare meglio e ho anche l'errore che non ci sono parametri per '.Select (KeyInterop.KeyFromVirtualKey)'? – beppe9000

Problemi correlati