2010-07-03 24 views
44

He estado trabajando durante un tiempo en mi proyecto Windows Forms, y decidí experimentar con los atajos de teclado. Después de un rato de lectura, pensé que tenía que acaba de escribir un controlador de eventos y enlazarlo a KeyDown del formulario evento:Formularios que no responden a eventos KeyDown

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 el buen camino viejo de abrir el panel Propiedades del diseñador de Visual Studio , haciendo 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 Ctrl + Alt + O atajo de teclado. El diseñador de Visual Studio hizo generar el código para enlazar el controlador de eventos a la forma embargo:

private void InitializeComponent() 
{ 
    // ... 

    this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown); 

    // ... 
} 

así que traté de añadir una llamada Console.WriteLine() al controlador para comprobar que estaba siendo llamado en absoluto, pero sin suerte en ese ya sea.

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 programa alcanza ese punto de interrupción muy bien. Pero nunca se alcanzan los puntos de interrupción que establecí dentro de la definición del método.

Para asegurarse de que estaba haciendo los primeros pasos correctamente, he intentado repetir con ellos:

  • Una nueva forma en la misma solución.
    mismo problema: el formulario no responde cuando se presiona mi Ctrl +Alt +O combinación de teclas y el depurador no es ni siquiera entrar en el controlador de eventos. Intenté esto de nuevo y funciona.

  • Una nueva solución de 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?

Respuesta

107

¿Su formulario tiene la propiedad KeyPreview establecida en verdadero?

Form.KeyPreview Propiedad

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

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

+0

No, así que lo cambié y eso lo resolvió. Gracias por su respuesta y el enlace de documentación. – BoltClock

+17

Es un truco, disponible para mantener contentos a los programadores de VB6. Tiene problemas de orden de ejecución, reemplaza a ProcessCmdKey() en su lugar. –

+0

@HansPassant, no encuentro nada que explique los problemas de orden de ejecución. KeyDown + KeyPreview no verá todas las claves, que es un problema suficiente, pero ¿cuáles son los problemas de orden de ejecución? – kdbanman

17

Trate de establecer la propiedad KeyPreview en su forma verdadera. Esto funcionó para registrar las pulsaciones de teclas.

+0

Sí, eso es todo! Muchas gracias. – BoltClock

23

La pieza más común de consejos para este problema en StackOverflow y la MSDN 1, 2 (incluyendo la respuesta aceptada aquí) es rápido y fácil:

KeyDown eventos se desencadenan en un Form siempre como su propiedad KeyPreview se establece en true

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

  1. KeyDown manipuladores do not see all keys. 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. Existen algunas maneras diferentes de interceptar eventos clave, y todos ocurren en secuencia. KeyDown se maneja ú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 para esos puntos.)

lugar, sustituya 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. Here es un artículo con más detalles.

+1

Esta es la respuesta correcta, especialmente si ve que PreviewKeyDown no se activará en absoluto con KeyPreview configurado en verdadero. – Tim

+0

Realmente, realmente útil. ¡Lo votaría dos veces si pudiera! Gracias –

Cuestiones relacionadas