c# - 在 C# 中处理 KeyDown 和 KeyPress 事件

标签 c# winforms keyboard-events

我正在尝试制作一个“键盘记录器”...好吧,它不完全是一个键盘记录器,因为它只显示击键而不将它们记录到文件中。我计划在我的 Google+ 环聊中使用它,这样我仍然可以显示我的按键操作,而无需将其与视频录制软件一起使用。

private void OnKeyDown(object sender, KeyEventArgs e)
{
    lblText.Text = "";
    lblText.Visible = false;

    boxSpKey.Image = null;
    boxSpKey.Visible = false;

    boxCtrl.Visible = e.Control;
    boxAlt.Visible = e.Alt;
    boxWin.Visible = false;
    boxShift.Visible = e.Shift;

    Keys pKey = e.KeyData;
    if (btnIcons.ContainsKey(pKey))
    {
        boxSpKey.Visible = true;
        boxSpKey.Image = btnIcons[pKey];
    }

    // this part I haven't figured out either, but is irrelevant to my question.
}

private void OnKeyPress(object sender, KeyPressEventArgs e)
{
    lblText.Visible = true;
    lblText.Text = ((char)e.KeyChar).ToString();
}

[Context: lblText 是包含按键文本的标签,boxSpKey 是用于 ESC 等特殊按键的 PictureBox,为此我我们把每一个都做成了一个图标。 boxCtrlboxAltboxWinboxShift 也是 PictureBoxes 相当自定的解释。]

问题:

  1. 看起来e.Controle.Alte.Shift的值总是False,所以相应的 PictureBoxes 将不会显示。

  2. 如何检查 Win 键的状态?我不想使用低级 VK_* 常量。

  3. OnKeyPress 处理事件时(主要是使用修饰键),我会得到随机字符...我如何准确地从中获取原始击键?即我想要使用 Ctrl+Shift+B 而不是


更新:我决定使用修饰键进行低级别操作,因此我使用了 P/Invoke:

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetKeyboardState(byte[] lpKeyState);

public static byte code(Keys key)
{
    return (byte)((int)key & 0xFF);
}

private void OnKeyDown(object sender, KeyEventArgs e)
{
    var array = new byte[256];
    GetKeyboardState(array);

    // ...

    if ((array[code(Keys.ControlKey)] & 0x80) != 0)
        boxCtrl.Visible = true;
    if ((array[code(Keys.LMenu)] & 0x80) != 0 || (array[code(Keys.RMenu)] & 0x80) != 0)
        boxAlt.Visible = true;
    if ((array[code(Keys.LWin)] & 0x80) != 0 || (array[code(Keys.RWin)] & 0x80) != 0)
        boxWin.Visible = true;
    if ((array[code(Keys.ShiftKey)] & 0x80) != 0)
        boxShift.Visible = true;

    // ...
}

好消息是我可以使用 CtrlWinShift 键,但不能使用 Alt ;除非 AltLMenuRMenu。给出了什么?

最佳答案

  1. CtrlAltShift 分别导致 ControlAltShift 在我的 KeyDown 事件处理程序中返回 true。单独按下这些键中的每一个都会导致我的 KeyUp 事件处理程序返回 false。您确定没有处理 KeyUp 事件吗?

  2. 正如 @sean woodward 所说, Windows Key 应映射到 Keys.LWinKeys.RWin

  3. KeyPress 事件仅在按下其中一个字符键时引发,并将返回由按下的按键或按下的按键组合产生的字符。 Ctrl+Shift+B 不是字符,因此您不能单独使用 KeyChar 来获取该信息。尝试使用 KeyDownKeyUp 事件并查看 Modifiers 属性以获取正在按下的修改键的逗号分隔字符串。如果顺序很重要,您需要跟踪它,因为 Modifiers 始终以相同的顺序返回按键,即 Shift、Control、Alt,即使这不是按下它们的方式。

这是我使用的代码,您可以尝试使用它:


KeyDown += (o, ea) =>
{
    System.Diagnostics.Debug.WriteLine("KeyDown => CODE: " + ea.KeyCode +
        ", DATA: " + ea.KeyData +
        ", VALUE: " + ea.KeyValue +
        ", MODIFIERS: " + ea.Modifiers +
        ", CONTROL: " + ea.Control +
        ", ALT: " + ea.Alt +
        ", SHIFT: " + ea.Shift);

};

KeyUp += (o, ea) =>
{
    System.Diagnostics.Debug.WriteLine("KeyUp => CODE: " + ea.KeyCode +
        ", DATA: " + ea.KeyData +
        ", VALUE: " + ea.KeyValue +
        ", MODIFIERS: " + ea.Modifiers +
        ", CONTROL: " + ea.Control +
        ", ALT: " + ea.Alt +
        ", SHIFT: " + ea.Shift);
};

KeyPress += (o, ea) => 
{
    System.Diagnostics.Debug.WriteLine("KeyPress => CHAR: " + ea.KeyChar);
};

关于c# - 在 C# 中处理 KeyDown 和 KeyPress 事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14917422/

相关文章:

c# - 在 C# 中以编程方式调整图像大小

c# - 唯一标识罗技统一键盘(在 C# 中)

c# - 整数值的 DataView LIKE 函数

c# - 更高效地将 WinForms 转换为 WPF 或将 WPF 转换为 Winforms

c# - Visual Studio 引用

python - 一次按下多个键让我的角色沿对角线移动

ios - 如何使用 native react 为 IOS 选择键盘类型

c# - 如何在 Windows 中使用 C# 检测进程开始和结束?

c# - 我应该使 C# 私有(private)方法通用吗?

c# - 为什么将动态对象类型转换为对象会抛出空引用异常?