Las teclas de flecha arriba, abajo, izquierda y derecha no disparan el evento KeyDown

Estoy construyendo una aplicación donde todas las entradas de claves deben ser manejadas por la misma ventana.

Establecí tabstop en falso para cada control que podría captar el foco excepto un panel (pero no sé si tiene efecto).

Establecí KeyPreview en verdadero y estoy manejando el evento KeyDown en este formulario.

Mi problema es que a veces las teclas de flecha ya no responden:

  • El evento de pulsación no se dispara cuando presioné solo una tecla de flecha.

  • El evento de tecla se dispara si presiono una tecla de flecha con el modificador de control.

¿Tienes una idea de por qué mi flecha de repente deja de disparar el evento?

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

Estaba teniendo exactamente el mismo problema. Consideré la respuesta @Snarfblam proporcionada; sin embargo, si lee la documentación en MSDN, el método ProcessCMDKey pretende anular los eventos clave de los elementos del menú en una aplicación.

Recientemente me encontré con este artículo de Microsoft, que parece bastante prometedor: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.previewkeydown.aspx . Según microsoft, lo mejor que se puede hacer es establecer e.IsInputKey=true; en el evento PreviewKeyDown después de detectar las teclas de flecha. Al hacerlo, se KeyDown evento KeyDown .

Esto funcionó bastante bien para mí y fue menos hack-ish que reemplazar la ProcessCMDKey.

Estoy usando 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; } } 

Ver la respuesta de Rodolfo Neuber a la mejor respuesta


(Mi respuesta original):

Derive de una clase de control y puede anular el método ProcessCmdKey. Microsoft optó por omitir estas claves de los eventos KeyDown porque afectan a múltiples controles y mueven el foco, pero esto hace que sea muy difícil hacer que una aplicación reaccione a estas claves de cualquier otra manera.

Desafortunadamente, es bastante difícil lograr esto con las teclas de flecha, debido a las restricciones en los eventos de KeyDown. Sin embargo, hay algunas formas de evitar esto:

  • Como dijo @Snarfblam, puede anular el método ProcessCmdKey , que conserva la capacidad de analizar las pulsaciones de las teclas de flecha.
  • Como afirma la respuesta aceptada en esta pregunta , XNA tiene un método incorporado llamado Keyboard.GetState () , que le permite utilizar las entradas de la tecla de flecha. Sin embargo, WinForms no tiene esto, pero se puede hacer a través de una P / Invoke , o mediante el uso de una clase que lo ayude .

Recomiendo tratar de usar esa clase. Es bastante simple hacerlo:

 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... 

Si usa esto en combinación con el evento KeyDown, creo que puede lograr su objective de manera confiable.

Tuve un problema similar al llamar a la ventana de WPF fuera de WinForms.

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

Sin embargo, al mostrar la ventana como un diálogo , funcionó

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

Espero que esto ayude.

Para capturar las pulsaciones de teclas en un control de Formularios, debe derivar una nueva clase que se basa en la clase del control que desea, y usted anula el ProcessCmdKey ().

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

Ejemplo:

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

Fuente completa … Teclas de flecha en C #

Vayne

La mejor manera de hacerlo, creo, es manejarlo como lo dijo MSDN en http://msdn.microsoft.com/en-us/library/system.windows.forms.control.previewkeydown.aspx

Pero maneja, cómo realmente lo necesitas. A mi manera (en el ejemplo a continuación) es atrapar cada KeyDown 😉

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

Tenía el mismo problema y ya estaba usando el código en la respuesta seleccionada. este enlace fue la respuesta para mí; quizás para otros también

Cómo deshabilitar la navegación en WinForm con las flechas en C #?