C# – 检查是否按下了特定键
我是C#编程的新手。 我正在尝试检查按键是否按下,但是我收到以下错误消息:“错误1当前上下文中不存在名称’键盘’”“错误2当前上下文中不存在名称’Key’ “你能告诉我怎么修理它吗?
//... using System.Windows.Input; class Main { public void Main() { while(true) { if(Keyboard.IsKeyPressed(Key.A)) { //... } return; } } }
您可以使用键盘钩子。 看看这个 ,从这个问题的答案 :
如果您只需要一些全局热键,则全局键盘挂钩不是正确的解决方案。 高级键盘挂钩意味着您的DLL将被注入其他应用程序,并且不应该在托管代码中完成。 低级键盘钩更好一点,因为它处理您自己的应用程序中的键盘事件。 仍然需要每个键盘事件都由您的线程处理。
Windows API函数RegisterHotKey更适合这种情况。
但是使用一个简单的F-Key作为全局热键是有问题的,因为它可能会与具有焦点的应用程序的本地热键发生冲突。 因此,您应该使全局热键可配置,以便用户可以避免与其常用应用程序发生冲突。
看起来您正在尝试在系统中创建全局热键,并且您的应用程序应在按下时响应。
您将需要两个Win32 API函数RegisterHotKey和UnregisterHotKey 。
看看你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); }
好的! 我们把它们放在哪里? 不要把它们放在构造函数中! 为什么? 因为Handle
将为0
并且无效! 把它们放在这里(在MainWindow
):
protected override void OnSourceInitialized(EventArgs e) { base.OnSourceInitialized(e); InitializeHook(); InitializeHotKey(); }
您可以注册多个热键,取消注册并重新注册新的热键。这取决于您。 请记住, 每个热键必须具有注册的唯一ID 。 它只是有意义,因为你的消息泵钩子必须知道哪个热键导致WM_HOTKEY
消息!
在应用程序关闭时取消注册所有热键也是一种很好的做法。
申请的类型对我来说并不清楚! 如果您有一个控制台应用程序,而不是Windows窗体应用程序,您可以尝试这样做:
while (true) { if (Console.KeyAvailable) if (Console.ReadKey(true).Key == ConsoleKey.A) { // Do something } }
如果你想在Windows窗体应用程序中有一个全局热键,请阅读此内容: http : //www.liensberger.it/web/blog/? p = 207
如果您尝试在Windows窗体应用程序中执行此操作,也许您可以将这些代码添加到窗体的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; }