Formularios que no responden a eventos KeyDown

He estado trabajando durante un tiempo en mi proyecto de Windows Forms, y decidí experimentar con los atajos de teclado. Después de leer un poco, pensé que tenía que escribir un controlador de eventos y vincularlo al evento KeyDown del formulario:

private void Form1_KeyDown(object sender, KeyEventArgs e) { if (e.Control && e.Alt && e.KeyCode == Keys.O) { MessageBox.Show("Ctrl+Alt+O: magic!"); } } 

Lo hice de la buena manera de abrir el panel Propiedades del diseñador de Visual Studio, y luego hacer doble clic en el evento KeyDown de mi formulario para generar el controlador de eventos Form1_KeyDown . Pero al probar mi aplicación, el formulario no responde en absoluto al atajo de teclado Ctrl + Alt + O. El diseñador de Visual Studio sí generó el código para vincular el controlador de eventos al formulario:

 private void InitializeComponent() { // ... this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown); // ... } 

Así que intenté agregar una llamada Console.WriteLine() al controlador para verificar que se estaba llamando, pero tampoco tuve suerte.

Además, traté de establecer un punto de interrupción en la llamada de enlace de eventos (que se muestra arriba) y encontré que el progtwig alcanza ese punto de interrupción sin problemas. Pero nunca se alcanzan los puntos de interrupción que establecí dentro de la definición del método.

Para asegurarme de estar haciendo los primeros pasos correctamente, intenté repetirlos con:

  • Una nueva forma en la misma solución.
    Mismo problema: el formulario no responde cuando presiono mi atajo de teclado Ctrl + Alt + O y el depurador ni siquiera está entrando en el controlador de eventos. Intenté esto de nuevo y funciona.

  • Una nueva solución WinForms.
    Funciona perfectamente: aparece el cuadro de diálogo del mensaje (la llamada Console.WriteLine() también funciona).

Así que estoy bastante perdido aquí. ¿Qué impide que todos los formularios de este proyecto reciban eventos KeyDown?

¿Su formulario tiene la propiedad KeyPreview establecida en verdadero?

Propiedad Form.KeyPreview

Obtiene o establece un valor que indica si el formulario recibirá eventos clave antes de pasar el evento al control que tiene el foco.

http://msdn.microsoft.com/en-us/library/system.windows.forms.form.keypreview.aspx

El consejo más común para este problema en StackOverflow y MSDN 1 , 2 (incluida la respuesta aceptada aquí) es rápido y fácil:

KeyDown eventos KeyDown se desencadenan en un Form siempre que su propiedad KeyPreview esté establecida en true

Eso es adecuado para la mayoría de los propósitos, pero es arriesgado por dos razones:

  1. KeyDown manejadores KeyDown no ven todas las claves . Específicamente, “no se puede ver el tipo de teclas que se utilizan para la navegación. Al igual que las teclas del cursor y Tab, Escape e Intro para un diálogo”.

  2. Hay algunas formas diferentes de interceptar eventos clave, y todos ocurren en secuencia. KeyDown se manejó el último . Por lo tanto, KeyPreview no es una buena vista previa, y el evento podría ser silenciado en unas pocas paradas en el camino.

(Crédito a @HansPassant por esos puntos).

En su lugar, anule ProcessCmdKey en su Form :

 protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { if (keyData == Keys.Up) { // Handle key at form level. // Do not send event to focused control by returning true. return true; } return base.ProcessCmdKey(ref msg, keyData); } 

De esta forma, todas las claves son visibles para el método, y el método es el primero en la cola para ver el evento.

Tenga en cuenta que todavía tiene control sobre si los controles enfocados ven el evento KeyDown . Simplemente devuelva true para bloquear el evento KeyDown posterior, en lugar de establecer KeyPressEventArgs.Handled en true como lo haría en un controlador de eventos KeyDown . Aquí hay un artículo con más detalles.

Intente establecer la propiedad KeyPreview en su formulario en verdadero. Esto funcionó para registrar las pulsaciones de teclas.