2012-05-07 14 views
5

Co muszę użyć, aby uzyskać "wszystkie klawisze", które są teraz naciskane na klawiaturze? Od Form.KeyPress += new EventHandler() nie robi wiele w ogóle, gdy jest pełen kontroli. Nie nazywa się tego bez względu na to, co robię, ani KeyDown, KeyUp ani cokolwiek innego ... i tak, wiem jak z nich korzystać.Pobierz wszystkie klawisze, które są wciśnięte

Tak więc, jeśli w systemie jest jakaś funkcja, która może sprawdzić wciśnięte klawisze, która zwraca tablicę użytych klawiszy lub coś takiego - byłbym wdzięczny za wskazanie we właściwym kierunku.

+1

Czy chcesz, aby wszystkie klawisze były naciskane podczas uruchamiania określonego fragmentu kodu, czy chcesz wydarzenie, które dzieje się po naciśnięciu klawisza? – zimdanen

+0

możliwy duplikat [najlepszy sposób implementacji skrótów klawiszowych w winformach?] (Http://stackoverflow.com/questions/400113/best-way-to-implement-keyboard-shortcuts-in-winforms) –

+0

Powiedz, że chcę mieć narzędzie do obsługi zdarzeń dla MouseWheel, ale chcę nacisnąć klawisz "Ctrl", gdy wykonuję coś w EventHandler. więc jeśli przewińę koło, otrzymam tylko wyniki koła myszy, a nie naciśnięcie klawisza. – Deukalion

Odpowiedz

12

Wygląda na to, że chcesz sprawdzić stan wszystkich klawiszy na klawiaturze. Najlepsza funkcja to Win32 Api zadzwoń GetKeyboardState

nie wierzę, nie jest dobrym udało równowartość tej funkcji. Kod PInvoke dla niego jest dość prosta

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

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

To zapełnić byte[] z góra/dół stanu każdego klucza wirtualnego w systemie. Jeśli ustawiony jest bit wysoki, to klawisz wirtualny jest aktualnie wciśnięty. Odwzorowanie kodu Key na kod klucza wirtualnego odbywa się przez uwzględnienie tylko wartości liczbowej wartości numerycznej.

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

Powyższe prace dla większości wartości Key ale trzeba być ostrożnym z klawiszy modyfikujących. Wartości i nie będą tutaj działać, ponieważ są to modyfikatory techniczne, a nie wartości kluczowe. Aby użyć modyfikatorów trzeba użyć faktyczne związane wartości klucza Keys.ControlKey, Keys.LShiftKey, itp ... (naprawdę coś, co kończy się klucz)

więc sprawdzenie, czy dany klucz jest ustawiony może być wykonane w następujący sposób

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

Działa również dla klawiszy modyfikujących, musisz jednak użyć klawiszy Keys.AltKey, ShiftKey i ControlKey. –

+0

@HansPassant dobry telefon, zapomniałem o tych wpisach – JaredPar

+0

Taa ... Ale ktoś, kto nie użył tych rzeczy przed nim, może dobrze opisać potrzebne mi przestrzenie nazw, dlaczego DllImport pokazuje kolor czerwony, dlaczego GetKeyboardState nie jest nigdzie znalezione , itp., itd ... Połowa wypalonych odpowiedzi oznacza, że ​​muszę wyszukiwać więcej, aby uzyskać odpowiedzi bez odpowiedzi. – Deukalion

0

Wydaje mi się, że szukasz zdarzenia o numerze PreviewKeyDown, które zostanie wywołane, jeśli podczas ustawiania ostrości zostanie naciśnięty klawisz, nawet jeśli inna kontrola podrzędna w tym formularzu ma obecnie fokus.

1

Jeśli potrzebujesz znać tylko wszystkie naciśnięcia klawiszy, gdy aplikacja jest aktywna, bez względu na to, która kontrola w aplikacji jest aktywna, możesz użyć właściwości formularza w postaci KeyPreview.

Po prostu ustaw właściwość na wartość true i zasubskrybuj żądane zdarzenia kluczowe w formularzu. Teraz otrzymasz wszystkie naciśnięcia klawiszy w aplikacji, zanim zostaną przekazane do konkretnej kontroli, dzięki czemu możesz na niej zareagować i anulować przekazywanie do kontroli, ustawiając właściwość Cancel na true.

Jeśli potrzebujesz otrzymać wciśnięte klawisze, gdy aplikacja nie jest aktywna, potrzebujesz haka niskiego poziomu. Nie testowałem tego, ale this article on CodeProject wygląda całkiem obiecująco w tym przypadku.

3

Rozszerzyłem nieco odpowiedź JaredPar.Poniższa metoda zwraca kolekcję wszystkich klawiszy, które są aktualnie naciskane:

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

Trudno mi przetłumaczyć przypisanie 'DistinctVirtualKeys' w VB.Net. Czy możesz skomentować to lepiej, a także otrzymuję komunikat o błędzie, że nie ma parametru dla '.Select (KeyInterop.KeyFromVirtualKey)'? – beppe9000

Powiązane problemy