如何捕获WPF中的键?

时间:2010-11-24 11:47:32

标签: wpf keyboard-events

即使我的应用程序没有聚焦,如何在WPF中捕获按键事件?

3 个答案:

答案 0 :(得分:3)

对我来说,最好的方法是:

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();
    }
} 

每次都会运行渲染事件。

答案 1 :(得分:1)

全局键盘挂钩会降低调试速度。

我更喜欢使用这种方法:

  1. 创建KeyboardListener类

    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();
            }
        });
    }
    }
    
  2. 在代码隐藏中(或您需要的地方)订阅KeyboardDownEvent。

    public partial class MainWindow : Window
    

    {     私有KeyboardListener侦听器;

    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;
    }
    

    }

  3. 完成

答案 2 :(得分:0)

有关挂钩键盘Using global keyboard hook (WH_KEYBOARD_LL) in WPF / C#

的信息,请参阅此问题