我是C#编程的新手。 我正在尝试检查是否按下了某个键,但是我收到以下错误消息: “错误1当前上下文中不存在名称'键盘'” “错误2当前上下文中不存在名称'Key'” 你能告诉我如何解决它吗?
//...
using System.Windows.Input;
class Main {
public void Main() {
while(true) {
if(Keyboard.IsKeyPressed(Key.A)) {
//...
}
return;
}
}
}
答案 0 :(得分:1)
您可以使用键盘钩子。从this
中查看this answer to a similar question如果您只想要一个,那么全局键盘钩子不是正确的解决方案 很少有全球热键。高级键盘钩意味着你的DLL 将注入其他应用程序,不应该完成 在托管代码中。一个低级别的键盘钩更好一点,因为它 处理您自己的应用程序中的键盘事件。还是它 要求每个键盘事件都由你的线程处理。
Windows API函数RegisterHotKey更适合 这一点。
但是使用一个简单的F-Key作为全局热键是有问题的,因为它可能 与具有焦点的应用程序的本地热键冲突。那么你 应该使全局热键可配置,以便用户可以避免 与他常用的应用程序碰撞。
答案 1 :(得分:0)
看起来您正在尝试在系统中创建全局热键,并且您的应用程序应该在按下时响应。
您需要两个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
消息!
在应用程序关闭时取消注册所有热键也是一种很好的做法。
答案 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;
}