WinForms 全局热键输入干扰
WinForms Global Hotkey Typing Interference
我正在尝试让这个键盘挂钩在按下时将注册的键回显到标签。我的目标是在 Window 失焦时执行此操作。
This program is only looking for the keys*: w, a, s, d
我遇到的问题 运行 是我无法在任何其他程序(例如:记事本)中键入字母 w, a, s, d
,而此程序是 运行。
这是我的表格 class:
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);
}
}
和它用来注册密钥的class:
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);
}
}
我要全部suggestions/answers。谢谢!
更新 1
我能够使用 Jimi 建议的 GetAsyncKeyState()。虽然这不会干扰输入其他 windows,但它不会更新我的应用程序 window,直到它重新聚焦。
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 and 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;
我正在尝试让这个键盘挂钩在按下时将注册的键回显到标签。我的目标是在 Window 失焦时执行此操作。
This program is only looking for the keys*:
w, a, s, d
我遇到的问题 运行 是我无法在任何其他程序(例如:记事本)中键入字母 w, a, s, d
,而此程序是 运行。
这是我的表格 class:
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);
}
}
和它用来注册密钥的class:
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);
}
}
我要全部suggestions/answers。谢谢!
更新 1
我能够使用 Jimi 建议的 GetAsyncKeyState()。虽然这不会干扰输入其他 windows,但它不会更新我的应用程序 window,直到它重新聚焦。
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 and 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;