【问题标题】:Why does pressing 2 keys simultaneously cause repeated KeyDown events that have IsRepeat set to false?为什么同时按下 2 个键会导致重复的 KeyDown 事件将 IsRepeat 设置为 false?
【发布时间】:2025-12-21 11:35:11
【问题描述】:

我正在使用 C# 和 WPF。当使用 KeyDown 事件处理程序来监视键盘输入时,一切正常。 按住 1 个键,甚至 2 个键时,一切都很好。 当我同时按下 2 个键并按住它们时,就会出现问题。当我这样做时,两个键的 KeyDown 事件被重复触发,并且 IsRepeat 值为 false。当您同时按住 2 个键时,它会反复触发新事件。

为什么会发生这种情况,我怎样才能让它不发生? 下面是一个 .net 核心 WPF 示例,我在其中监视 KeyDown 事件并查找 A 或 S 键。我可以按住 A,我可以按住 S,我的代码只会为每个生成一次非重复事件。我什至可以连续快速按下它们。
如果我同时按下并按住它们,则会重复生成新的非重复 KeyDown 事件。这就是我试图阻止或了解它发生的原因。

MainWindow.xaml.cs:

using System.Windows;
 using System.Windows.Input;
    
 namespace TwoSimultaneousKeyDowns
 {
     public partial class MainWindow : Window
     {
         public MainWindow()
         {
             InitializeComponent();
         }
         private void OnKeyDownHandler(object sender, KeyEventArgs e)
         {
             //If A or S is pressed
             if (e.Key.ToString() == "A" || e.Key.ToString() == "S")
             {
                 //Checks if it is a repeat event (repeats happen when you hold the button down)
                 if (!e.IsRepeat)
                 {
                     txtBox1.Text += e.Key.ToString() + " was pressed.\r\n";
                 }
             }
         }
     }
 }

MainWindow.xaml:

 <Window x:Class="TwoSimultaneousKeyDowns.MainWindow"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:local="clr-namespace:TwoSimultaneousKeyDowns"
         mc:Ignorable="d"
         Title="MainWindow" Height="450" Width="800" KeyDown="OnKeyDownHandler">
     <Grid Focusable="True">
         <Grid.ColumnDefinitions>
             <ColumnDefinition />
         </Grid.ColumnDefinitions>
         <TextBox x:Name="txtBox1" Grid.Column="1" HorizontalAlignment="Center" TextWrapping="Wrap" VerticalAlignment="Center" Height="400" Width="300"/>
     </Grid>

【问题讨论】:

  • 不要将枚举值与字符串进行比较。始终将其与另一个枚举(相同的集合)进行比较:if (e.Key == Key.A)。不确定你观察到什么。您可能对条件检查感到困惑。您已反转 IsRepeated ,因此在重复键时不会看到 TextBox 的任何输出。 “我可以按住A,我可以按住S,我的代码只会为每个生成一个非重复事件。我什至可以连续快速按下它们。”:这是正确的根据你的实现行为。
  • 如果我使用此代码同时按下 A 和 S,这是我得到的输出,直到我松开:A 被按下。 S被按下。 A被按下。 S被按下。 A被按下。 S被按下。 A被按下。 S被按下。 A 被按下。

标签: c# wpf


【解决方案1】:

" 我可以按住 A,我可以按住 S,我的代码将 只为每个生成一次非重复事件。我什至可以按下它们 快速连续。”

根据您的实现,这是正确的行为。

您目前没有检查同时按下的键。您只是在过滤两个单独的按键事件:'A' OR 'S'。
使用的逻辑应该表明您的代码是错误的。同时只能表示为逻辑AND

检查同时按下的键的正确实现是:

protected override void OnKeyDown(KeyEventArgs e)
{
  base.OnKeyDown(e);

  //If A AND S is pressed
  if (e.KeyboardDevice.IsKeyDown(Key.A) && e.KeyboardDevice.IsKeyDown(Key.S))
  {
    //Checks if it is a repeat event (repeats happen when you hold the button down)
    if (e.IsRepeat)
    {
      return;
    }

    txtBox1.Text += e.Key.ToString() + " was pressed.\r\n";
  }
}

【讨论】:

  • 这不能回答我的问题或帮助。您的示例代码仅检查 A & S 是否同时被按住。我不关心检查。我可以按住 A 并按住它,我的代码只输出“A 被按下”一次。在按住A的同时,我也可以开始按住S,无论按住多久,“S被按下”只会输出一次。我关心的问题是,当我同时按下 A 和 S 时,会发生新的意外行为。 “A 被按下”和“S 被按下”填满了窗口,直到我放手,它们的 IsRepeat 值都是假的。
  • 我明白了。我只在整个地方“同时”阅读。甚至您的命名空间也称为“TwoSimultaneousKeyDowns”。所以我假设你的目标是检测“TwoSimultaneousKeyDowns”。正常行为是,如果您按住一个键的时间足够长以超过重复延迟阈值,则该事件被解释为重复按键。这是在操作系统级别处理的。这意味着您应该检查您的键盘设置。
  • 这甚至可能与硬件有关。您是否尝试过测试不同的键?你应该试试键盘另一端的键。
  • 是的,试过了。甚至尝试了多台电脑/键盘。如果您运行示例代码,我希望它也会对您执行此操作。
  • 我刚刚运行了您的示例代码,它表现正常 - 正如预期的那样。如果这种简单但常见的场景无法正常工作,WPF 键盘输入处理将毫无用处。我无法重现您的问题。如果您没有任何其他冲突的键盘事件处理程序,那么这似乎与 WPF 无关。这不是我第一次使用关键事件处理程序,相信我,您可以尝试建立一个新的空项目并再次测试它。您还可以尝试使用 Win32 键盘挂钩来证明它与 WPF 无关。但我会先从一个新的空白解决方案和 WPF 输入处理开始。
最近更新 更多