问题描述
我试图让这个键盘钩子在按下时将注册的键回显到标签。我的目标是在 Window 失焦时执行此操作。
这个程序只寻找密钥*:w,a,s,d
我遇到的问题是,在此程序运行时,我无法在任何其他程序(例如:记事本)中输入字母 w,d
。
这是我的表单类:
Form1.cs:
public partial class Form1 : Form
{
private KeyHandler _keyHandler;
private List<Keys> keys = new List<Keys>() { Keys.W,Keys.A,Keys.S,Keys.D };
public Form1()
{
InitializeComponent();
foreach (var key in keys) (_keyHandler = new KeyHandler(key,this)).Register();
}
private void Form1_KeyDown(object sender,KeyEventArgs e)
{
label1.Text = e.KeyCode.ToString();
}
// Key Logger =======================
private void HandleHotkey(int keyPress)
{
if (keyPress == 5701632)
label1.Text = "W pressed";
else if (keyPress == 4259840)
label1.Text = "A pressed";
else if (keyPress == 5439488)
label1.Text = "S pressed";
else if (keyPress == 4456448)
label1.Text = "D pressed";
}
protected override void WndProc(ref Message m)
{
if (m.Msg == Constants.WM_HOTKEY_MSG_ID)
HandleHotkey(m.LParam.ToInt32());
base.WndProc(ref m);
}
}
以及它用来注册密钥的类:
KeyHandler.cs:
public static class Constants
{
//windows message id for hotkey
public const int WM_HOTKEY_MSG_ID = 0x0312;
}
public class KeyHandler
{
[DllImport("user32.dll")]
private static extern bool RegisterHotKey(IntPtr hWnd,int id,int fsModifiers,int vk);
[DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd,int id);
private int key;
private IntPtr hWnd;
private int id;
public KeyHandler(Keys key,Form form)
{
this.key = (int)key;
this.hWnd = form.Handle;
id = this.GetHashCode();
}
public override int GetHashCode()
{
return key ^ hWnd.ToInt32();
}
public bool Register()
{
return RegisterHotKey(hWnd,id,key);
}
public bool Unregiser()
{
return UnregisterHotKey(hWnd,id);
}
}
我会接受所有建议/答案。谢谢!
更新 1
我可以使用 Jimi 建议的 GetAsyncKeyState()。虽然这不会干扰在其他窗口中输入,但它不会更新我的应用程序窗口,直到它重新成为焦点。
Form1.cs
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void HandleHotkey(Keys key)
{
label1.Text = key.ToString() + " done";
}
protected override void WndProc(ref Message m)
{
KeyState keyState = new KeyState();
if (keyState.GetKeyState(Keys.W) == 1) HandleHotkey(Keys.W);
base.WndProc(ref m);
}
}
KeyState.cs
public class KeyState
{
[DllImport("user32.dll")]
public static extern short GetAsyncKeyState(Keys key);
public int GetKeyState(Keys key)
{
return GetAsyncKeyState(key);
}
}
解决方法
解决方案
在Jimi和this stack overflow form的帮助下,我解决了我遇到的问题。
通过使用方法 GetAsyncKeyState() 和计时器,我能够不断检查键 w,a,s,d
是否被按下。
Form1.cs
public partial class Form1 : Form
{
[DllImport("user32.dll")]
public static extern short GetAsyncKeyState(Keys key);
public Form1()
{
InitializeComponent();
StartTimer(timer1_Tick);
}
private void timer1_Tick(object sender,EventArgs e)
{
if (GetAsyncKeyState(Keys.W) <= -32767) label1.Text = Keys.W + " special";
else if (GetAsyncKeyState(Keys.A) <= -32767) label1.Text = Keys.A + " special";
else if (GetAsyncKeyState(Keys.S) <= -32767) label1.Text = Keys.S + " special";
else if (GetAsyncKeyState(Keys.D) <= -32767) label1.Text = Keys.D + " special";
else label1.Text = "Nothing Pressed";
}
private void StartTimer(EventHandler eventHandler)
{
timer1.Tick += new EventHandler(eventHandler);
timer1.Interval = 35;
timer1.Start();
}
}
将此添加到 Form1.Designer.cs
public System.Windows.Forms.Timer timer1;