上,下,左,右箭头键不会触发KeyDown事件

我正在build立一个应用程序,所有的关键input必须由Windows本身处理。

我设置tabstop为false为每个控制女巫可以抓住焦点除了面板(但我不知道它是否有效果)。

我将KeyPreview设置为true,并处理此窗体上的KeyDown事件。

我的问题是,有时箭头键不响应了:

  • 当我只按下箭头键时,keydown事件不会被触发。

  • 如果我用控制修饰符按下箭头键,keydown事件被触发。

你有一个想法,为什么我的箭头键突然停止射击事件?

protected override bool IsInputKey(Keys keyData) { switch (keyData) { case Keys.Right: case Keys.Left: case Keys.Up: case Keys.Down: return true; case Keys.Shift | Keys.Right: case Keys.Shift | Keys.Left: case Keys.Shift | Keys.Up: case Keys.Shift | Keys.Down: return true; } return base.IsInputKey(keyData); } protected override void OnKeyDown(KeyEventArgs e) { base.OnKeyDown(e); switch (e.KeyCode) { case Keys.Left: case Keys.Right: case Keys.Up: case Keys.Down: if (e.Shift) { } else { } break; } } 

我有完全相同的问题。 我认为答复@Snarfblam提供; 但是,如果您阅读MSDN上的文档,则ProcessCMDKey方法旨在覆盖应用程序中菜单项的关键事件。

我最近偶然发现了微软的这篇文章,看起来很有前景: http : //msdn.microsoft.com/en-us/library/system.windows.forms.control.previewkeydown.aspx 。 根据微软,最好的事情是设置e.IsInputKey=true; 在检测到箭头键后的PreviewKeyDown事件中。 这样做会触发KeyDown事件。

这对我来说工作得非常好,比重写ProcessCMDKey要less得多。

从控件类派生,您可以重写ProcessCmdKey方法。 微软select从KeyDown事件中省略这些键,因为它们会影响多个控件并移动焦点,但是这使得应用程序以任何其他方式对这些键作出反应是非常困难的。

我正在使用PreviewKeyDown

  private void _calendar_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e){ switch (e.KeyCode){ case Keys.Down: case Keys.Right: //action break; case Keys.Up: case Keys.Left: //action break; } } 

不幸的是,由于KeyDown事件的限制,使用箭头键很难完成这个任务。 但是,有几种方法可以解决这个问题:

  • 正如@Snarfblam所述,您可以重写ProcessCmdKey方法 ,该方法保留了parsing箭头按键的function。
  • 正如从这个问题接受的答案所述,XNA有一个名为Keyboard.GetState()的内置方法,它允许您使用箭头键input。 但是,WinForms没有这个,但是可以通过P / Invoke ,或者使用一个帮助它的类来完成

我build议尝试使用该类。 这样做很简单:

 var left = KeyboardInfo.GetKeyState(Keys.Left); var right = KeyboardInfo.GetKeyState(Keys.Right); var up = KeyboardInfo.GetKeyState(Keys.Up); var down = KeyboardInfo.GetKeyState(Keys.Down); if (left.IsPressed) { //do something... } //etc... 

如果您将此与KeyDown事件结合使用,我认为您可以可靠地完成您的目标。

从WinForms中调用WPF窗口时遇到类似的问题。

 var wpfwindow = new ScreenBoardWPF.IzbiraProjekti(); ElementHost.EnableModelessKeyboardInterop(wpfwindow); wpfwindow.Show(); 

然而,将窗口显示为对话框 ,它工作

 var wpfwindow = new ScreenBoardWPF.IzbiraProjekti(); ElementHost.EnableModelessKeyboardInterop(wpfwindow); wpfwindow.ShowDialog(); 

希望这可以帮助。

为了捕获在一个窗体控件中的击键,您必须派生一个基于您所需的控件类的新类,然后重写ProcessCmdKey()。

 protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { //handle your keys here } 

例如:

 protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { //capture up arrow key if (keyData == Keys.Up ) { MessageBox.Show("You pressed Up arrow key"); return true; } return base.ProcessCmdKey(ref msg, keyData); } 

完整的源代码… 在C#中的箭头键

Vayne

我认为最好的方法就是像MSDN上的http://MSdn.microsoft.com/en-us/library/system.windows.forms.control.previewkeydown.aspx

但处理它,你真的需要它。 我的方式(在下面的例子中)是捕获每个KeyDown 😉

  /// <summary> /// onPreviewKeyDown /// </summary> /// <param name="e"></param> protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e) { e.IsInputKey = true; } /// <summary> /// onKeyDown /// </summary> /// <param name="e"></param> protected override void OnKeyDown(KeyEventArgs e) { Input.SetFlag(e.KeyCode); e.Handled = true; } /// <summary> /// onKeyUp /// </summary> /// <param name="e"></param> protected override void OnKeyUp(KeyEventArgs e) { Input.RemoveFlag(e.KeyCode); e.Handled = true; } 

我有同样的问题,并已使用所选答案中的代码。 这个链接是我的答案。 也许也是为了别人。

如何使用C#中的箭头禁用WinForm导航?