C# c键盘挂钩:e.按键事件时控件始终为false

C# c键盘挂钩:e.按键事件时控件始终为false,c#,hook,keyeventargs,C#,Hook,Keyeventargs,我正在为一项研究记录用户的行为,参加研究的人都知道他们的行为被记录了,因此我一直在用C语言构建一个小键盘记录器 多亏了msdn文档和一些教程,我可以用KeyPressEvent使一些东西工作得很好,但现在我5天前意识到我在使用ctrl、alt修饰符时遇到了问题。我发现我必须使用KeyDown和keydup事件来记录论文 以下是我的windows窗体代码和位于Hook.cs类中的KeyProc函数: private IntPtr KeyProc(int nCode, int wParam, Int

我正在为一项研究记录用户的行为,参加研究的人都知道他们的行为被记录了,因此我一直在用C语言构建一个小键盘记录器

多亏了msdn文档和一些教程,我可以用KeyPressEvent使一些东西工作得很好,但现在我5天前意识到我在使用ctrl、alt修饰符时遇到了问题。我发现我必须使用KeyDown和keydup事件来记录论文

以下是我的windows窗体代码和位于Hook.cs类中的KeyProc函数:

private IntPtr KeyProc(int nCode, int wParam, IntPtr lParam)
    {
        bool handled = false;
        //On verifie si tous est ok
        if ((nCode >= 0) && (m_onKeyDown != null || m_onKeyUp != null || m_onKeyPress != null))
        {
            KeyboardHookStruct MyKeyboardHookStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
            //KeyDown


            if (m_onKeyDown != null && (wParam == 0x100 || wParam == 0x104))
            {
                Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;
                KeyEventArgs e = new KeyEventArgs(keyData);
                m_onKeyDown(this, e);
                handled = handled || e.Handled;
            }

            // KeyPress
            if (m_onKeyPress != null && wParam == 0x100)
            {
                bool isShift = ((GetKeyState(0x10) & 0x80) == 0x80 ? true : false);
                bool isCapslock = (GetKeyState(0x14) != 0 ? true : false);

                //bool isCtrl = (GetKeyState(0x11) != 0 ? true : false);
                //bool isAlt = (GetKeyState(0x12) != 0 ? true : false);

                byte[] keyState = new byte[256];
                GetKeyboardState(keyState);
                byte[] inBuffer = new byte[2];
                if (ToAscii(MyKeyboardHookStruct.vkCode,
                          MyKeyboardHookStruct.scanCode,
                          keyState,
                          inBuffer,
                          MyKeyboardHookStruct.flags) == 1)
                {
                    char key = (char)inBuffer[0];
                    if ((isCapslock ^ isShift) && Char.IsLetter(key))
                        key = Char.ToUpper(key);

                    KeyPressEventArgs e = new KeyPressEventArgs(key);
                    m_onKeyPress(this, e);
                    handled = handled || e.Handled;
                }
            }

            // KeyUp
            if (m_onKeyUp != null && (wParam == 0x101 || wParam == 0x105))
            {
                Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;
                KeyEventArgs e = new KeyEventArgs(keyData);
                m_onKeyUp(this, e);
                handled = handled || e.Handled;
            }
        }

private void OnKeyUp(object sender, KeyEventArgs e)
    {
        if (e.Control)
            flagD = false;
    }

    private void OnKeyDown(object sender, KeyEventArgs e)
    {
        textBox1.Text += e.KeyCode;
        flagD = e.Control ? true : false;
        textBox1.Text += " " + flagD;    
    }

我不明白为什么e.Control总是错误的,我一直在文本框中使用e.KeyCode;我可以看到ControlKey被记录,但我不明白为什么flagD总是false。

因为您忘记将它们包含在keyData中。比如isCtrl keyData |=Keys.Control;请记住,当另一个进程具有焦点时按下该键时,这是不准确的。键盘状态是每个线程的属性。出于同样的原因,ToAscii也不可能准确。正确执行此操作需要一个WH_键盘钩子,无法在C.thx中写入这些钩子作为答案,我不知道如何更改属性,这是主要问题。实际上,对于那些关心的人,我对每个非系统密钥使用了一个标志系统。我映射一个类Flags.cs中的所有内容,并在keypup/keypdown事件中更新flag.cs中调用适当方法的标志,例如:按下ctrl,启动Onkeypdown事件。ctrl->1;ctrl被释放,OnkeyUp被提升flag=0@Hans我不知道我是否理解你,但我使用的是全局钩子,键盘和鼠标的低级钩子不需要特殊的dll。即使窗口没有焦点,它也能工作。