C# WinForms全局热键键入干扰

C# WinForms全局热键键入干扰,c#,winforms,keyboard-hook,registerhotkey,C#,Winforms,Keyboard Hook,Registerhotkey,我试图让这个键盘钩子在按下时将注册的键回显到标签上。我的目标是在窗口失去焦点时执行此操作 此程序仅查找键*:w、a、s、d 我遇到的问题是,当该程序运行时,我无法在任何其他程序(例如:记事本)中键入字母w、a、s、d 这是我的表格课: 表格1.cs: 我接受所有建议/答案。谢谢大家! 更新1 我能够使用建议的GetAsyncKeyState()。虽然这不会影响在其他窗口中键入内容,但它不会更新我的应用程序窗口,直到它重新聚焦 表格1.cs 公共部分类表单1:表单 { 公共表格1() {

我试图让这个键盘钩子在按下时将注册的键回显到标签上。我的目标是在窗口失去焦点时执行此操作

此程序仅查找键*:
w、a、s、d


我遇到的问题是,当该程序运行时,我无法在任何其他程序(例如:记事本)中键入字母
w、a、s、d


这是我的表格课:

表格1.cs:


我接受所有建议/答案。谢谢大家!


更新1 我能够使用建议的GetAsyncKeyState()。虽然这不会影响在其他窗口中键入内容,但它不会更新我的应用程序窗口,直到它重新聚焦

表格1.cs

公共部分类表单1:表单
{
公共表格1()
{
初始化组件();
}
私有无效HandleHotkey(密钥)
{
label1.Text=key.ToString()+“完成”;
}
受保护的覆盖无效WndProc(参考消息m)
{
KeyState KeyState=新的KeyState();
if(keyState.GetKeyState(key.W)==1)HandleHotkey(key.W);
基准WndProc(参考m);
}
}
KeyState.cs

公共类键状态
{
[DllImport(“user32.dll”)]
公共静态外部短GetAsyncKeyState(key);
public int GetKeyState(键)
{
返回GetAsyncKeyState(键);
}
}
解决方案 在和的帮助下,我解决了我遇到的问题

通过使用该方法和定时器,我能够不断地检查按键
w、a、s、d
是否被按下


表格1.cs

公共部分类表单1:表单
{
[DllImport(“user32.dll”)]
公共静态外部短GetAsyncKeyState(key);
公共表格1()
{
初始化组件();
起始计时器(计时器1_刻度);
}
私有无效计时器1_刻度(对象发送方,事件参数e)
{

如果通过在代码中使用
switch
方法中的
m.LParam
值解决了(GetAsyncKeyState(Keys.W)问题#2,则将热键ID设置为
ID=this.GetHashCode();
在处理程序类中。您可能应该为添加的每个热键使用一个基ID,即递增,并将该ID存储在处理程序类中。相反,每次创建一个新的热键时,您都会覆盖一个处理程序对象。--在LPRAM中,热键ID是
int hotKeyID=m.WParam.ToInt32();
,按下的键是
var keyPressed=(Keys)(m.LParam.ToInt32()>>16);
和修饰符
var修饰符=(KeyModifier)(m.LParam.ToInt32()&0xFF);
。热键是全局性的,在键盘输入之前进行处理,因此您可以主动从标准输入中删除该键。也许您需要这样做?--顺便说一句,您应该将代码发布到此处。我认为您正在使用所有消息,因此没有其他应用程序可以获取这些消息。要在您的窗口处于非活动状态时获取击键,您可能需要注册一个H_KEYBOARD\u LL这不应该消耗消息
GetAsyncKeyState()
不返回
bool
,它返回
SHORT
SHORT
)。--对于WinForms计时器来说
16ms
间隔太小,不要将其设置在
35ms
以下(官方最大分辨率为
55ms
)@Jimi我同意35ms计时器。但是如果需要,
GetAsyncKeyState()
会返回bool。我使用
if(GetAsyncKeyState(Keys.W)==true)label1.Text=GetAsyncKeyState(Keys.W).ToString()测试了这一点
并且它在屏幕上打印了
True
。我相信你说返回一个short是有很好的理由的,所以请让我知道。不,它没有,它返回一个
short
,其中
MSB
LSB
有特定的含义。你不应该为它没有的内容封送一个值,它可能会变得古怪,通常带有错误的timing:)@Jimi更新了我的if语句,以检查键的大小。您可以检查
GetAsyncKeyState()
返回的值是否设置了
MSB
(如
未选中((short)0b1000\u 0000\u 0001)
,这当然是
-32767
)。在您链接的答案中,
MSB
向右移动15个位置(
((keyState>>15)和0x0001)=0x0001
),并与
1
进行比较,以查看是否设置了
MSB
。请参阅相关文档。
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);
    }
}
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);
    }
}
public System.Windows.Forms.Timer timer1;