2013-02-17 153 views
2

我试图制作一个“键盘记录器”......好吧,它不完全是一个键盘记录程序,因为它只显示击键并且不会将它们记录到文件中。我打算在我的Google+环聊中使用它,所以我仍然可以在不用视频录制软件的情况下显示我的按键。在C#中处理KeyDown和KeyPress事件#

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(); 
} 

[上下文:lblText是包含关键文本的标签,boxSpKey为特殊键,如ESC,我已完成针对每一个图标的PictureBoxboxCtrlboxAltboxWinboxShiftPictureBox ES是相当不言自明]

问题:

  1. 看来的e.Controle.Alte.Shift值始终是假的,所以相应的PictureBox es不会出现。

  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; 

    // ... 
} 

的好消息是,我得到了Ctrl,WinShift键工作,但不是Alt;除非AltLMenuRMenu。是什么赋予了?

+0

怎么样使用密钥对e.Modifiers财产比较,http://msdn.microsoft.com/ EN-US /库/ system.windows.forms.keys.aspx?请参阅LWin和RWin以获取Windows键。 – 2013-02-17 02:55:01

+1

在我的键盘上按下'Alt'键会在我的处理程序中产生'Keys.Menu'的'KeyCode'值。它似乎没有区分左侧和右侧。不幸的是,我没有其他键盘可以测试。 – gowansg 2013-02-17 18:24:43

+0

@gowansg奇怪的......'LMenu'和'RMenu'键应该检查两侧的Alt键,但似乎只是'Keys.Menu'工作。谢谢〜 – 2013-02-17 19:18:55

回答

1
  1. 按下Ctrl键Alt键,或单独引起ControlAltShift在我KeyDown事件处理程序返回true。单独按下这些键中的每一个导致在我的KeyUp事件处理程序中返回false。你确定你没有处理KeyUp事件吗?

  2. 正如@sean伍德沃德表示,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); 
};