Cuando la codificación de un pequeño juego, me he encontrado con un problema; mi forma de KeyDown y KeyUp eventos no fuego.

Este es el código del formulario:

public class GameForm : Form
{
    private ControllableBlock player;

    public GameForm()
    {
        KeyDown += Game_KeyDown;
        KeyUp += Game_KeyUp;

        player = new ControllableBlock();
        Controls.Add(player);
    }

    private void Game_KeyDown(object sender, KeyEventArgs e)
    {
        player.ReactToKey(e.KeyCode);
    }

    private void Game_KeyUp(object sender, KeyEventArgs e)
    {
        player.ReactToKey(e.KeyCode);
    }
}

Hay muchas más cosas, pero yo sólo pega el código correspondiente.

Ya he probado la configuración de this.KeyPreview = true; y llamadas this.Focus();, ninguno de los dos trabajos.
El problema no está en ReactToKey() método, ya he establecer un punto de interrupción no existe y el caso es que nunca disparó.


Edición: Después de algunas pruebas he llegado a la conclusión de que el problema está dentro de mi ControllableBlock.
Sin embargo, no tengo idea por qué, pero estoy trabajando en ello.
Si yo comente todo lo relacionado con la player, los acontecimientos empiezan a disparar.


Edit 2: Parece que el problema es que me heredar mi ControllableBlock de Control.
Si me lo heredan de Panel, funciona bien.
¿Por qué es esto?
No puedo despedir a un evento si me heredar de control?

El ControllableBlock clase está vacía, por ahora, por lo que incluso no hacer otra cosa que hereda de Control.


Edit 3: Ahora que he empezado una recompensa, me gustaría aclarar que yo no estoy buscando una solución en la forma de hacer los eventos de fuego, estoy buscando una razón de por qué no el fuego si yo heredar de Control.

  • player.Obstacles.Add(obstacle); ¿qué sucede aquí? Traté de reproducir el problema, pero todos eventhandlers con this.KeyPreview = true funciona bien (excepto las teclas de flecha – va a pensar acerca de la solución aquí). Sin esta línea, de hecho ninguno de los eventos se activan
  • No sé por qué el tuyo no funciona, pero a mí me funciona. Basta con crear un nuevo control, cuando se muestra el formulario, el enfoque que el control como este Shown += (s,e) => { myControl.Focus(); }; y, a continuación, presione alguna tecla, que hace el trabajo. Si desea centrar su control por ratón, creo que no es enfocado de esa manera y que pensaba que no funcionaba?
InformationsquelleAutor | 2013-02-26

4 Comentarios

  1. 3

    Yo era capaz de reproducir un problema similar (que con suerte relacionados..)

    Explicación:

    • Controles que volver CanSelect==true son seleccionables para la entrada de teclado
    • En blanco descendiente de Control() es seleccionable, uno de Panel() no es
    • La primera seleccionable control agregar a un formulario recibirá seleccionado
    • Un control seleccionado se roban los eventos de teclado de sus padres por defecto
    • Ciertas teclas que se utilizan para la navegación dentro de una ventana requieren pasos adicionales para ser manipulable

    De verificación aquí para una buena visión general de cómo windows entrada de teclado funciona.

    Código para reproducir:

    public class GameForm : Form
    {
        public GameForm()
        {
            this.KeyDown += Game_KeyDown;
            var tests = new List<Control[]>() { 
                new[] { new Panel() },
                new[] { new Panel(), new Panel() },
                new[] { new Control() },
                new[] { new Control(), new Panel() },
                new[] { new Panel(), new Control() }
            };
            //When test index 2 to 4 used, keyboard input does not reach form level
            Controls.AddRange(tests[0]);            
            //When uncommented, ensures all keyboard input reaches form level
            /*this.KeyPreview = true;              
            //Additional plumbing required along with KeyPreview to allow arrow and other reserved keys
            foreach (Control control in this.Controls)
            {
                control.PreviewKeyDown += control_PreviewKeyDown;
            }*/
        }
        void control_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            e.IsInputKey = true;
        }
        private void Game_KeyDown(object sender, KeyEventArgs e)
        {
            //breakpoint here
            Debug.WriteLine(e.KeyCode);
        }
    }
    • Esta respuesta puede ser interesante, pero no es ningún tipo de ayuda para resolver el problema.
  2. 4

    Si tus eventos deben ser de nivel de aplicación intenta establecer la propiedad KeyPreview a true – le permite a fuego respectivos eventos, independientemente de control enfocado.

    this.KeyPreview = true;

    De lo contrario usted debe adjuntar estos eventos directamente para controlar que el proceso de ellos.

    Edición:

    He quitado InitializeComponent(); de mi formulario y consiguió un comportamiento idéntico al suyo.

    Después de la implementación de la solución proporcionada en este pregunta todos los eventos comenzaron a qork perfectamente.

    Copia el fragmento de código aquí:

    protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
            if (keyData == Keys.Left) {
                //Do your staff for Left Key here
    
                return true;
            }
            //you need to add if condition to every direction you want to handle
            return base.ProcessCmdKey(ref msg, keyData);
        }
    • Él está haciendo lo correcto. Usted acaba de hacerlo el viejo pre-.Net 2 camino.
    • esta es la forma en VS2012 genera con ellos .Net 4.5… aprendido algo nuevo hoy mismo, gracias. Editado respuesta a resaltar otra opción posible
    • Por desgracia, que ya he mencionado en mi post principal. Leer las ediciones más recientes para obtener información adicional.
    • editado mi respuesta – por favor, eche un vistazo por si ayuda
    • Sí, ya he encontrado esto, pero yo preferiría no anular la ProcessCmdKey. Me siento más curiosidad sobre por qué mi programa no funciona si lo heredé de mi clase de Control, pero funciona si lo heredé de Panel.
    • realmente debe ser primordial ProcessCmdKey. El KeyPreview propiedad está allí sólo para compatibilidad hacia atrás con VB 6. Usted necesita porque KeyDown y KeyUp de lo contrario, sólo se aplican cuando el control tiene el foco, y de la forma en sí nunca tendrá el foco si se ha seleccionable de los niños. ProcessCmdKey soluciona ese problema. @Markus
    • Sí sé que hoy en día, no entonces. Mi proyecto ya no existe, sólo tengo curiosidad sobre por qué heredar de Control desactiva la clave de los eventos, pero la herencia de Panel no.

  3. 0

    Usted necesita para hacer de su control seleccionable antes de que pueda recibir el foco.

    Trate de añadir el siguiente a su constructor:

    this.SetStyle(ControlStyles.Selectable, true);

    Y asegurarse de que usted proporcione en el formulario de enfoque después de que ha sido mostrada. O, anular OnMouseDown() y llamar a este.Focus() en ella.

    • No hay diferencia :/
  4. 0

    trate de mover el controlador de la instalación para el evento Form_Load en lugar de el constructor. No debería ser una llamada a Initialize() en el constructor? Yo no lo recomendamos especialmente la eliminación de lo

    Si ControllableBlock hereda de Panel, va a tener más conexiones y una mejor interfaz de usuario de la interacción de la instalación de una base en el objeto de Control.

    • Inicializar qué? Todo esto está la mano codificados y yo no uso el diseñador en todo. Todo lo que necesita ser inicializado, se inicializa en el constructor. Form_Load evento no ayuda tampoco. Lo hizo fuego tho, por lo que el problema está dentro de la keyevents.

Dejar respuesta

Please enter your comment!
Please enter your name here