2009-07-20 17 views
6

Tengo un control de usuario con varios controles secundarios. Necesito que la interfaz de usuario reaccione a las pulsaciones de teclas, así que decidí poner el código de manejo en un evento MainControl_KeyDown. Sin embargo, cuando presiono una tecla en mi aplicación, este evento no se dispara.Capturar eventos KeyDown en un UserControl

He encontrado una solución a través de un motor de búsqueda que se basa en el uso de la API de Windows, que me gustaría evitar, ya que parece exagerado para lo que debería ser una función que sea soportada por .NET Framework.

+2

encontré [esta respuesta] [1] para ser el más útil - se reemplaza ProcessCmdKey(). [1]: http://stackoverflow.com/a/1616965/327458 – bsegraves

+0

Este enlace debe ser la respuesta. – OfficeAddinDev

Respuesta

7

Se podría agregar un controlador de eventos KeyDown para cada control secundario en el control de usuario y desencadenar el evento KeyDown del control de usuario en cada uno, así:

private void textBox1_KeyDown(object sender, KeyEventArgs e) 
{ 
    this.OnKeyDown(e); 
} 
1

tal vez debería manejar todos los eventos localmente y luego disparar los eventos ficticios para comunicarse con el control principal?

o tal vez esto puede ser un problema de enfoque; si hay muchos controles secundarios y solo uno de ellos está enfocado, los otros no reaccionarán con la acción de bajar la tecla.

quizás podría publicar algunos fragmentos de código aquí para estar seguro.

1

Aquí es un ejemplo de ese bucle tirar cada control en la forma de adjuntar el evento KeyDown. Es como la respuesta previouly en este post pero manejar más casos:

using Microsoft.VisualBasic; 
using System; 
using System.Collections; 
using System.Collections.Generic; 
using System.Data; 
using System.Diagnostics; 

public class UserControlKeyboardProcessor 
{ 
    private void Control_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e) 
    { 
     base.OnKeyDown(e); 
    } 

    private void UserControlKeyboardProcessor_Disposed(object sender, System.EventArgs e) 
    { 
     foreach (System.Windows.Forms.Control control in this.GetAllControls(this)) { 
      control.KeyDown -= Control_KeyDown; 
     } 
    } 

    private void UserControlKeyboardProcessor_Load(object sender, System.EventArgs e) 
    { 
     foreach (System.Windows.Forms.Control control in this.GetAllControls(this)) { 
      control.KeyDown += Control_KeyDown; 
     } 
    } 

    public Generic.List<System.Windows.Forms.Control> GetAllControls(System.Windows.Forms.Control control) 
    { 
     Generic.List<System.Windows.Forms.Control> controls = new Generic.List<System.Windows.Forms.Control>(); 

     foreach (System.Windows.Forms.Control subControl in control.Controls) { 
      controls.Add(subControl); 
      controls.AddRange(this.GetAllControls(subControl)); 
     } 

     return controls; 
    } 
    public UserControlKeyboardProcessor() 
    { 
     Load += UserControlKeyboardProcessor_Load; 
     Disposed += UserControlKeyboardProcessor_Disposed; 
    } 
} 
9

Sé que este hilo es un poco viejo, pero tuve un problema similar y manejado de una manera diferente:
En la ventana principal Cambié el atributo KeyPreview a verdadero. He registrado el controlador KeyDown-event de la ventana principal en mi control de usuario.

this.Parent.KeyDown += new KeyEventHandler(MyControl_KeyDown); 

Esto me impide enrutar el evento KeyDown de cada control secundario a mi control de usuario.
Por supuesto, es importante eliminar el controlador de eventos cuando descarga su control de usuario.

Espero que esto ayude a las personas que enfrentan un problema similar ahora.

+0

Esto funciona muy bien cuando se usa un control en múltiples formas y capturando 'Enter' llama a un método en la forma – Wayne

0

Tengo un truco.

UcBase heredan de UesrControl

UcSub1 y UcSub2 heredan de UcBase. UcSuperClass también hereda de UcBase.

UcSub1, UcSub2 uso en UcSuperClass.

I loco UcSub1 y UcSub2 invocan ProcessCmdKey ok.

mis códigos fue

public class UcBase : UserControl 
{ 
    public delegate bool ProcessCmdKeyHandler(Keys keyData); 

    public ProcessCmdKeyHandler KeyHandler; 

    protected override void OnLoad(EventArgs e) 
    { 
     base.OnLoad(e); 

     KeyHandler += ProcessKey; 

     if (Parent != null) 
     { 
      var parent = GetParentControl<UcBase>(Parent); 

      if (parent != null) 
      { 
       parent.KeyHandler += ProcessKey; 
      } 
     } 
    } 

    protected virtual bool ProcessKey(Keys keyData) 
    { 
     return false; 
    } 

    protected override bool ProcessCmdKey(ref Message msg, Keys keyData) 
    { 
     const int WM_KEYDOWN = 0x100; 
     const int WM_SYSKEYDOWN = 0x104; 

     if (KeyHandler != null 
      && (msg.Msg == WM_KEYDOWN) || (msg.Msg == WM_SYSKEYDOWN)) 
     { 
      if (KeyHandler(keyData) == true) 
      { 
       return true; 
      } 
     } 

     return base.ProcessCmdKey(ref msg, keyData); 
    } 

    private T GetParentControl<T>(Control control) 
     where T : Control 
    { 
     T parentControl = default(T); 
     var queue = new Queue<Control>(); 
     var targetControlType = typeof(T); 

     queue.Enqueue(control.Parent); 

     while (queue.Count > 0) 
     { 
      var parent = queue.Dequeue(); 

      if (parent != null) 
      { 
       if (parent.GetType().BaseType == targetControlType) 
       { 
        parentControl = (T)parent; 

        break; 
       } 
       else 
       { 
        queue.Enqueue(parent.Parent); 
       } 
      } 
      else 
      { 
       break; 
      } 
     } 

     return parentControl; 
    } 
} 

public class UcSub1 : UcBase 
{ 
    protected override bool ProcessKey(Keys keyData) 
    { 
     // if you process do something, and return true then UcBase.ProcessCmdKey pass by. 
     return false; 
    } 
} 

public class UcSub2 : UcBase 
{ 
    protected override bool ProcessKey(Keys keyData) 
    { 
     // if you process do something, and return true then UcBase.ProcessCmdKey pass by. 
     return false; 
    } 
} 

public class UcSuperClass : UcBase 
{ 
    private UcSub1 _ucSub1; 
    private UcSub2 _ucSub2; 

    public UcSuperClass() 
    { 
     _ucSub1 = new UcSub1(); 
     _ucSub2 = new UcSub2(); 
    } 

    protected override bool ProcessKey(Keys keyData) 
    { 
     // if you process do something, and return true then UcBase.ProcessCmdKey pass by. 
     return false; 
    } 
} 
5

Usted puede agregar a su following methodusercontrol:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) 
{ 
    if ((keyData == Keys.Right) || (keyData == Keys.Left) || 
     (keyData == Keys.Up) || (keyData == Keys.Down)) 
    { 
    //Do custom stuff 
    //true if key was processed by control, false otherwise 
    return true; 
    } 
    else 
    { 
    return base.ProcessCmdKey(ref msg, keyData); 
    } 
} 
Cuestiones relacionadas