C# - 检查是否按下了特定键

时间:2013-12-27 16:35:25

标签: c# keyboard key

我是C#编程的新手。 我正在尝试检查是否按下了某个键,但是我收到以下错误消息: “错误1当前上下文中不存在名称'键盘'” “错误2当前上下文中不存在名称'Key'” 你能告诉我如何解决它吗?

//...
using System.Windows.Input;

class Main {
    public void Main() {
        while(true) {
            if(Keyboard.IsKeyPressed(Key.A)) {
                //...
            }
            return;
        }
    }
}

4 个答案:

答案 0 :(得分:1)

您可以使用键盘钩子。从this

中查看this answer to a similar question
  

如果您只想要一个,那么全局键盘钩子不是正确的解决方案   很少有全球热键。高级键盘钩意味着你的DLL   将注入其他应用程序,不应该完成   在托管代码中。一个低级别的键盘钩更好一点,因为它   处理您自己的应用程序中的键盘事件。还是它   要求每个键盘事件都由你的线程处理。

     

Windows API函数RegisterHotKey更适合   这一点。

     

但是使用一个简单的F-Key作为全局热键是有问题的,因为它可能   与具有焦点的应用程序的本地热键冲突。那么你   应该使全局热键可配置,以便用户可以避免   与他常用的应用程序碰撞。

答案 1 :(得分:0)

看起来您正在尝试在系统中创建全局热键,并且您的应用程序应该在按下时响应。

您需要两个Win32 API函数RegisterHotKeyUnregisterHotKey

查看您的using System.Windows.Input,您似乎正在尝试使用WPF执行此操作,这是可能的。

让我们从相当基本的P / Invokes开始:

using System.Runtime.InteropServices;

internal static class NativeMethods
{
    [DllImport("user32.dll")]
    public static extern bool RegisterHotKey(IntPtr windowHandle, int hotkeyId, uint modifierKeys, uint virtualKey);

    [DllImport("user32.dll")]
    public static extern bool UnregisterHotKey(IntPtr windowHandle, int hotkeyId);
}

现在,当您注册Window时,会发生一条WM_HOTKEY消息发送到您应用程序的消息泵。但是,WPF将此消息抽象远离您,因此您需要添加HwndSourceHook才能使用它。

我们如何做到这一切?让我们从初始化HwndSourceHook代表开始。将此代码段添加到MainWindow

    using System.Windows.Interop;

    static readonly int MyHotKeyId = 0x3000;
    static readonly int WM_HOTKEY = 0x312;

    void InitializeHook()
    {
        var windowHelper = new WindowInteropHelper(this);
        var windowSource = HwndSource.FromHwnd(windowHelper.Handle);

        windowSource.AddHook(MessagePumpHook);
    }

    IntPtr MessagePumpHook(IntPtr handle, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        if (msg == WM_HOTKEY)
        {
            if ((int)wParam == MyHotKeyId)
            {
                // The hotkey has been pressed, do something!

                handled = true;
            }
        }

        return IntPtr.Zero;
    }

好的,现在我们已经准备好了应对WM_HOTKEY消息的所有内容。但是,我们还需要注册我们的热键!让我们添加另外几个初始化方法:

    void InitializeHotKey()
    {
        var windowHelper = new WindowInteropHelper(this);

        // You can specify modifiers such as SHIFT, ALT, CONTROL, and WIN.
        // Remember to use the bit-wise OR operator (|) to join multiple modifiers together.
        uint modifiers = (uint)ModifierKeys.None;

        // We need to convert the WPF Key enumeration into a virtual key for the Win32 API!
        uint virtualKey = (uint)KeyInterop.VirtualKeyFromKey(Key.A);

        NativeMethods.RegisterHotKey(windowHelper.Handle, MyHotKeyId, modifiers, virtualKey);
    }

    void UninitializeHotKey()
    {
        var windowHelper = new WindowInteropHelper(this);
        NativeMethods.UnregisterHotKey(windowHelper.Handle, MyHotKeyId);
    }

好的!我们把它们放在哪里? 不要将它们放在构造函数中!为什么?因为Handle0无效!把它们放在这里(MainWindow):

    protected override void OnSourceInitialized(EventArgs e)
    {
        base.OnSourceInitialized(e);
        InitializeHook();
        InitializeHotKey();
    }

您可以注册多个热键,取消注册并重新注册新的热键。这取决于您。请记住每个热键必须在其中注册一个唯一ID 。它只是有意义,因为你的消息泵钩子必须知道哪个热键导致了WM_HOTKEY消息!

在应用程序关闭时取消注册所有热键也是一种很好的做法。

答案 2 :(得分:0)

我不清楚申请的类型!如果你有一个控制台应用程序,而不是Windows窗体应用程序,你可以试试这个:

while (true) {
  if (Console.KeyAvailable) 
    if (Console.ReadKey(true).Key == ConsoleKey.A)
    { 
      // Do something
    }
}

如果您想在Windows窗体应用中使用全局热键,请阅读此内容:http://www.liensberger.it/web/blog/?p=207

答案 3 :(得分:0)

如果您尝试在Windows窗体应用程序中执行此操作,也许您可​​以将这些代码添加到Form的KeyDown事件中(或您需要使用的键事件):

switch (e.KeyData)
{
    //Detects that you pressed the Up Arrow Key, which key do you need, just 
    //write it here.
    case Keys.Up: 
    //enter code here`
    break;
}