C# trying to capture the KeyDown event on a form

后端 未结 4 1027
不知归路
不知归路 2020-12-03 07:25

I am creating a small game, the game is printed onto a panel on a windows form. Now i want to capture the keydown event to see if its the arrow keys that has been pressed, t

相关标签:
4条回答
  • 2020-12-03 07:47

    Have you set the KeyPreview property of the form to true? That will cause the form to get a "first look" at key events.

    Update: getting this to work properly when a Button has focus seems to be a bit tricky. The Button control intercepts the arrow key presses and moves focus to the next or previous control in the tab order in a manner so that the KeyDown, KeyUp and KeyPress events are not raised. However, the PreviewKeyDown event is raised, so that can be used:

    private void Form_KeyDown(object sender, KeyEventArgs e)
    {
        e.Handled = ProcessKeyDown(e.KeyCode);
    }
    
    // event handler for the PreViewKeyDown event for the buttons
    private void ArrowButton_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
    {
        ProcessKeyDown(e.KeyCode);
    
    }
    
    private bool ProcessKeyDown(Keys keyCode)
    {
        switch (keyCode)
        {
            case Keys.Up:
                {
                    // act on up arrow
                    return true;
                }
            case Keys.Down:
                {
                    // act on down arrow
                    return true;
                }
            case Keys.Left:
                {
                    // act on left arrow
                    return true;
                }
            case Keys.Right:
                {
                    // act on right arrow
                    return true;
                }
        }
        return false;
    }
    

    Still, the focus moves around in a rather ugly manner...

    0 讨论(0)
  • 2020-12-03 07:55
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            KeyPreview = true;
            KeyDown += new KeyEventHandler(Form1_KeyDown);
        }
    
        void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            System.Diagnostics.Debug.Write(e.KeyCode);
        }
    }
    
    0 讨论(0)
  • 2020-12-03 07:58

    Override IsInputKey behaviour


    You must override the IsInputKey behavior to inform that you want the Right Arrow key to be treated as an InputKey and not as a special behavior key. For that you must override the method for each of your controls. I would advise you to create your won Buttons, let's say MyButton

    The class below creates a custom Button that overrides the IsInputKey method so that the right arrow key is not treated as a special key. From there you can easily make it for the other arrow keys or anything else.

        public partial class MyButton : Button
        {
            protected override bool IsInputKey(Keys keyData)
            {
                if (keyData == Keys.Right)
                {
                    return true;
                }
                else
                {
                    return base.IsInputKey(keyData);
                }
            }
        }
    

    Afterwards, you can treat your keyDown event event in each different Button or in the form itself:

    In the Buttons' KeyDown Method try to set these properties:

    private void myButton1_KeyDown(object sender, KeyEventArgs e)
    {
      e.Handled = true;
      //DoSomething();
    }
    

    -- OR --

    handle the common behaviour in the form: (do not set e.Handled = true; in the buttons)

    private void Form1_KeyDown(object sender, KeyEventArgs e)
    {
        //DoSomething();
    }
    
    0 讨论(0)
  • 2020-12-03 07:58

    I believe the easiest way of solving this problem is through overriding the ProcessCmdKey() method of the form. That way, your key handling logic gets executed no matter what control has focus at the time of keypress. Beside that, you even get to choose whether the focused control gets the key after you processed it (return false) or not (return true).
    Your little game example could be rewritten like this:

    protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
    {
        if (keyData == Keys.Left)
        {
            MoveLeft(); DrawGame(); DoWhatever();
            return true; //for the active control to see the keypress, return false
        }
        else if (keyData == Keys.Right)
        {
            MoveRight(); DrawGame(); DoWhatever();
            return true; //for the active control to see the keypress, return false
        }
        else if (keyData == Keys.Up)
        {
            MoveUp(); DrawGame(); DoWhatever();
            return true; //for the active control to see the keypress, return false
        }
        else if (keyData == Keys.Down)
        {
            MoveDown(); DrawGame(); DoWhatever();
            return true; //for the active control to see the keypress, return false
        }
        else
            return base.ProcessCmdKey(ref msg, keyData);
    }
    
    0 讨论(0)
提交回复
热议问题