WPF:如何在Key *事件中检测Key重复?

时间:2009-12-04 16:06:24

标签: c# .net wpf .net-3.5 keyboard-events

注意e.IsRepeat已确认有效。问题的存在是因为我使用从Ubuntu到Windows的远程桌面。

我找到了此远程桌面问题的解决方法:

  1. 在Ubuntu中禁用密钥重复。
  2. 在主机Windows中:使用“打开重复键和慢键”启用FilterKeys
  3. 使用regedit转到HKEY_CURRENT_USER\Control Panel\Accessibility\Keyboard Response
    1. AutoRepeatDelayAutoRepeatRate Last Valid DelayLast Valid Repeat设置得足够小。
    2. 禁用FilterKeys并重新启用以刷新注册表更改。

  4. 如何检测KeyUp / KeyDown(或PreviewKeyDown / PreviewKeyUp)事件中的密钥重复?

    我有以下测试用例:

        public Window1() {
            InitializeComponent();
    
            this.KeyDown += new KeyEventHandler(Window1_KeyDown);
            this.KeyUp += new KeyEventHandler(Window1_KeyUp);
        }
    
        void Window1_KeyUp(object sender, KeyEventArgs e) {
            if (e.Key == Key.D) {
                Console.WriteLine("DOWN: key: {0}, rep{1}, togg{2}, dow{3}, up{4}", e.Key, e.IsRepeat, e.IsToggled, e.IsDown, e.IsUp);
            }
        }
    
        void Window1_KeyDown(object sender, KeyEventArgs e) {
            if (e.Key == Key.D) {
                Console.WriteLine("UP: key: {0}, rep{1}, togg{2}, dow{3}, up{4}", e.Key, e.IsRepeat, e.IsToggled, e.IsDown, e.IsUp);
            }
        }
    

    如果我按下字母D并在一段时间后释放它,它会给我输出屏幕

    // Note: Here I press D-key down.
    UP: key: D, repFalse, toggTrue, dowTrue, upFalse
    DOWN: key: D, repFalse, toggTrue, dowFalse, upTrue
    UP: key: D, repFalse, toggFalse, dowTrue, upFalse
    DOWN: key: D, repFalse, toggFalse, dowFalse, upTrue
    UP: key: D, repFalse, toggTrue, dowTrue, upFalse
    DOWN: key: D, repFalse, toggTrue, dowFalse, upTrue
    UP: key: D, repFalse, toggFalse, dowTrue, upFalse
    DOWN: key: D, repFalse, toggFalse, dowFalse, upTrue
    UP: key: D, repFalse, toggTrue, dowTrue, upFalse
    DOWN: key: D, repFalse, toggTrue, dowFalse, upTrue
    UP: key: D, repFalse, toggFalse, dowTrue, upFalse
    DOWN: key: D, repFalse, toggFalse, dowFalse, upTrue
    UP: key: D, repFalse, toggTrue, dowTrue, upFalse
    DOWN: key: D, repFalse, toggTrue, dowFalse, upTrue
    UP: key: D, repFalse, toggFalse, dowTrue, upFalse
    DOWN: key: D, repFalse, toggFalse, dowFalse, upTrue
    UP: key: D, repFalse, toggTrue, dowTrue, upFalse
    DOWN: key: D, repFalse, toggTrue, dowFalse, upTrue
    UP: key: D, repFalse, toggFalse, dowTrue, upFalse
    DOWN: key: D, repFalse, toggFalse, dowFalse, upTrue
    UP: key: D, repFalse, toggTrue, dowTrue, upFalse
    DOWN: key: D, repFalse, toggTrue, dowFalse, upTrue
    UP: key: D, repFalse, toggFalse, dowTrue, upFalse
    DOWN: key: D, repFalse, toggFalse, dowFalse, upTrue
    // Note: Here I release D-key.
    

    显然e.IsRepeat总是假的,所以没用。我还注意到有时第一个事件也是toggFalse,dowTrue,因此不能用作模式。

    我还注意到,使用计时的聪明方法可用于检测重复,但必须有一种本机方式来执行此操作。

2 个答案:

答案 0 :(得分:8)

为什么不使用原生的可能性?我在窗口和两个文本框中添加了一个PreviewKeyDown事件。按下并按住第二个文本框中的一个键,这是输出:

Repeat: False, key: D
Repeat: True, key: D
Repeat: True, key: D
Repeat: True, key: D
Repeat: True, key: D
Repeat: True, key: D
Repeat: True, key: D
Repeat: True, key: D

这是我使用的代码:

private void Grid_PreviewKeyDown(object sender, KeyEventArgs e)
{
    textBox1.Text += String.Format(
        "Repeat: {0}, key: {1}\n", 
        e.IsRepeat, 
        e.Key);
}

更新: 删除了我的所有代码(其他测试中有一些垃圾)并按原样粘贴在您的代码中。它在控制台中给出了以下输出,所以我想我们应该看看其他原因......

UP: key: D, repFalse, toggTrue, dowTrue, upFalse
UP: key: D, repTrue, toggTrue, dowTrue, upFalse
UP: key: D, repTrue, toggTrue, dowTrue, upFalse
UP: key: D, repTrue, toggTrue, dowTrue, upFalse
UP: key: D, repTrue, toggTrue, dowTrue, upFalse
UP: key: D, repTrue, toggTrue, dowTrue, upFalse

答案 1 :(得分:0)

当keydown事件触发跟踪按下哪个键时设置变量,执行您的操作(tm)然后忽略该键的其他事件。当keyup触发清除变量时。您可能需要一个列表来跟踪多个密钥。