How do I capture key down in WPF?
How do I capture a key down event in WP开发者_如何学JAVAF even if my application is not focused?
For me, the best way is this:
public MainWindow()
{
InitializeComponent();
CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
}
void CompositionTarget_Rendering(object sender, EventArgs e)
{
if ((Keyboard.GetKeyStates(Key.W) & KeyStates.Down) > 0)
{
player1.walk();
}
}
The rendering event runs every time.
Global keyboard hook can slow down your debugging.
I prefer to use this approach:
Create KeyboardListener class
public class KeyboardListener : IDisposable { private readonly Thread keyboardThread; //Here you can put those keys that you want to capture private readonly List<KeyState> numericKeys = new List<KeyState> { new KeyState(Key.D0), new KeyState(Key.D1), new KeyState(Key.D2), new KeyState(Key.D3), new KeyState(Key.D4), new KeyState(Key.D5), new KeyState(Key.D6), new KeyState(Key.D7), new KeyState(Key.D8), new KeyState(Key.D9), new KeyState(Key.NumPad0), new KeyState(Key.NumPad1), new KeyState(Key.NumPad2), new KeyState(Key.NumPad3), new KeyState(Key.NumPad4), new KeyState(Key.NumPad5), new KeyState(Key.NumPad6), new KeyState(Key.NumPad7), new KeyState(Key.NumPad8), new KeyState(Key.NumPad9), new KeyState(Key.Enter) }; private bool isRunning = true; public KeyboardListener() { keyboardThread = new Thread(StartKeyboardListener) { IsBackground = true }; keyboardThread.Start(); } private void StartKeyboardListener() { while (isRunning) { Thread.Sleep(15); if (Application.Current != null) { Application.Current.Dispatcher.Invoke(() => { if (Application.Current.Windows.Count > 0) { foreach (var keyState in numericKeys) { if (Keyboard.IsKeyDown(keyState.Key) && !keyState.IsPressed) // { keyState.IsPressed = true; KeyboardDownEvent?.Invoke(null, new KeyEventArgs(Keyboard.PrimaryDevice, PresentationSource.FromDependencyObject(Application.Current.Windows[0]), 0, keyState.Key)); } if (Keyboard.IsKeyUp(keyState.Key)) { keyState.IsPressed = false; } } } }); } } } public event KeyEventHandler KeyboardDownEvent; /// <summary> /// Состояние клавиши /// </summary> private class KeyState { public KeyState(Key key) { this.Key = key; } public Key Key { get; } public bool IsPressed { get; set; } } public void Dispose() { isRunning = false; Task.Run(() => { if (keyboardThread != null && !keyboardThread.Join(1000)) { keyboardThread.Abort(); } }); } }
Subscribe to KeyboardDownEvent in code-behind (or where you need it).
public partial class MainWindow : Window { private KeyboardListener listener; public MainWindow() { InitializeComponent(); } private void Window_Loaded(object sender, RoutedEventArgs e) { listener = new KeyboardListener(); listener.KeyboardDownEvent += ListenerOnKeyPressed; } private void ListenerOnKeyPressed(object sender, KeyEventArgs e) { // TYPE YOUR CODE HERE } private void Window_OnUnloaded(object sender, RoutedEventArgs e) { listener.KeyboardDownEvent -= ListenerOnKeyPressed; } }
Done
See this questions for hooking the keyboard Using global keyboard hook (WH_KEYBOARD_LL) in WPF / C#
精彩评论