Search code examples
c#.netwinformspictureboxkeypress

Move PictureBox using Arrow Keys - Handle keyboard events in PictureBox


I have a PictureBox where I use the code below to move my object. I need to add a few buttons in the form, however when I start the program the arrow keys navigate through the buttons instead of my input keypresses. I've tried many ways like PictureBox.Focus() and PictureBox.Select() on Form.Load(), and disabling the arrow key navigation completely on this answer here, but my object will not move anymore.

private void UpdateScreen(object sender, EventArgs e) {

    if (Input.KeyPressed(Keys.Right) && Settings.direction != Direction.Left) {
        Settings.direction = Direction.Right;
    }
    else if (Input.KeyPressed(Keys.Left) && Settings.direction != Direction.Right) {
        Settings.direction = Direction.Left;
    }  
    else if (Input.KeyPressed(Keys.Up) && Settings.direction != Direction.Down) {
        Settings.direction = Direction.Up;
    }
    else if (Input.KeyPressed(Keys.Down) && Settings.direction != Direction.Up) {
        Settings.direction = Direction.Down;
    }
}

How do I just disable the arrow key navigation for all my buttons without affecting my code in UpdateScreen()?


Solution

  • PictureBox control is not Selectable and therefore it can not handle Keyboard events. To solve the problem, you should first make the control selectable:

    using System;
    using System.Windows.Forms;
    class SelectablePictureBox : PictureBox
    {
        public SelectablePictureBox()
        {
            SetStyle(ControlStyles.Selectable, true);
            SetStyle(ControlStyles.UserMouse, true);
            TabStop = true;
        }
    
        protected override void OnEnter(EventArgs e)
        {
            base.OnEnter(e);
            this.Invalidate();
        }
        protected override void OnLeave(EventArgs e)
        {
            base.OnLeave(e);
            this.Invalidate();
        }
        protected override void OnPaint(PaintEventArgs pe)
        {
            base.OnPaint(pe);
            if (this.Focused)
                ControlPaint.DrawFocusRectangle(pe.Graphics, ClientRectangle);
        }
    }
    

    Then you can handle PreviewKeyDown event of it:

    private void selectablePictureBox1_PreviewKeyDown(object sender,
        PreviewKeyDownEventArgs e)
    {
        if (e.KeyCode == Keys.Left)
        {
            e.IsInputKey = true;
            myPictureBox1.Left -= 10;
        }
        else if (e.KeyCode == Keys.Right)
        {
            e.IsInputKey = true;
            myPictureBox1.Left += 10;
        }
    }