代码之家  ›  专栏  ›  技术社区  ›  Ciantic

WPF:如何在key*事件中检测密钥重复?

  •  7
  • Ciantic  · 技术社区  · 16 年前

    注释 : e.IsRepeat 确认工作。问题是存在的,因为我使用 从Ubuntu到Windows的远程桌面。

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

    1. 禁用Ubuntu中的重复键。
    2. 在主机窗口中:使用“打开重复键和慢速键”启用筛选键
    3. 使用regedit转到 HKEY_CURRENT_USER\Control Panel\Accessibility\Keyboard Response
      1. 集合 AutoRepeatDelay , AutoRepeatRate , 和 Last Valid Delay ,请 Last Valid Repeat 足够小。
      2. 禁用filterkey并重新启用以刷新注册表更改。

    如何检测钥匙重复 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重复序列 总是错的,所以没用。我还注意到,有时第一个事件也是同时发生的,所以不能用作模式。

    我还注意到,使用计时的巧妙方法可以用来检测重复,但必须有一种本地方法来做到这一点。

    2 回复  |  直到 15 年前
        1
  •  8
  •   Abel    16 年前

    为什么不利用本土的可能性呢?我在窗口和两个文本框中添加了一个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
    
        2
  •  0
  •   Mike B    16 年前

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