我正试图让这个键盘钩子在按下时将注册键回显到标签。我的目标是在窗口失焦时做到这一点。
这个程序只查找键*:
w, a, s, d
我遇到的问题是,当这个程序运行时,我不能在任何其他程序(例如:记事本)中键入字母w, a, s, d
。
这是我的Form类:
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, 0, 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和这个堆栈溢出表单的帮助下,我能够解决我遇到的问题。
通过使用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;