如何在 c# 中的 keyDown 事件上移动面板 up/down

How to move panels up/down on keysDown event in c#

我有 4 个面板,具有相同的 Y 和不同的 X,它们是在程序启动时在图片框上创建的。当我点击面板时,它会设置焦点并准备好接收 keysDown 事件,也就是说,如果我点击向上箭头键,面板就会向上移动。

这是代码:

public partial class FormView : Form
{
    List<CircleButton> myPanels = new List<CircleButton>(); // array of panels CircleButton
    Point[] arrayPoints_milestones; // array of X,Y
    int index;

    public FormView()
    {
        InitializeComponent();

        arrayPoints_milestones = new Point[4];
        for (int i = 0; i < 4; i++ )
        {
            arrayPoints_milestones[i] = new Point { X = 20, Y = 20 };
        }

        test();
    }

    protected void panel_Click(object sender, EventArgs e)
    {
        myPanels[index].PreviewKeyDown -= new PreviewKeyDownEventHandler(panel_KeyDown);

        CircleButton panel = sender as CircleButton;

        index = (int)panel.Tag;

        myPanels[index].Focus(); //panel.Focus();            
        myPanels[index].PreviewKeyDown += new PreviewKeyDownEventHandler(panel_KeyDown);
    }

    private void panel_KeyDown(object sender, PreviewKeyDownEventArgs e)
    {         
        if (e.KeyCode == Keys.Up)
        {
            myPanels[index].Centre = new Point(myPanels[index].Centre.X, myPanels[index].Centre.Y - 10);
            MessageBox.Show("" + myPanels[index].Centre.Y);

            Invalidate();
        }
        if (e.KeyCode == Keys.Down)
        {
            myPanels[index].Centre = new Point(myPanels[index].Centre.X, myPanels[index].Centre.Y + 10);
            MessageBox.Show("" + myPanels[index].Centre.Y);

            Invalidate();                
        }    
    }

    private void test()
    {
        //for (int i = 0; i < 4; i++)
        int i=0;
        foreach(var value in arrayPoints_milestones)
        {
            CircleButton panel = new CircleButton();
            panel.Tag = i;
            panel.Centre = new Point(arrayPoints_milestones[i].X + i * 10, arrayPoints_milestones[i].Y);
            panel.Radius = 10;
            panel.BackColor = Color.Red;
            panel.Message = "Index: " + panel.Tag.ToString();

            myPanels.Add(panel); // qui aggiungo il pannello alla lista di pannelli myPanels 

            pictureBox1.Controls.Add(myPanels[i]);
            myPanels[i].Click += new EventHandler(panel_Click);

            i++;
        }
    }

}

这是自定义面板 class:

public class CircleButton : Panel
{
    //Properties to draw circle
    float radius;
    public float Radius
    {
        get { return radius; }
        set
        {
            radius = value;
            this.Size = new Size((int)Radius, (int)Radius);
        }
    }

    public string Name
    {
        get;
        set;
    }

    Point centre;
    public Point Centre
    {
        get { return centre; }

        set
        {
            centre = value;
            this.Location = Centre;
        }
    }

    public string Message { get; set; }

    public CircleButton()
    {
        //Default Values
        Name = "panel_base";
        this.BackColor = Color.Black;
        Radius = 1;
        Centre = new Point(0, 0);
        this.DoubleBuffered = true;
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);

        //Defines a graphic path and set it as the panel's region
        //For custom region use different path's
        if (centre != null)
        {
            GraphicsPath path = new GraphicsPath();
            path.AddEllipse(0, 0, radius, radius);
            this.Region = new Region(path);
            path.Dispose();
        }
    }        
}

每次点击一个面板,都会添加一个PreviewKeyDownEventHandler - 所以3次点击会触发3(不同)具有相同调用目标的事件处理程序,每个事件处理程序都会将您的面板移动 10 个像素 up/down:

protected void panel_Click(object sender, EventArgs e) {
    CircleButton panel = sender as CircleButton;

    index = (int)panel.Tag;

    myPanels[index].Focus(); //panel.Focus();
    myPanels[index].PreviewKeyDown += new PreviewKeyDownEventHandler(panel_KeyDown);
}


FormView 的更新代码:

public partial class FormView : Form {
    List<CircleButton> myPanels = new List<CircleButton>(); // local use only in my example
    Point[] arrayPoints_milestones; //not needed anymore
    int index; //not needed anymore

    public FormView() {
        InitializeComponent();
        this.Load += FormView_Load;
    }

    void FormView_Load(object sender, EventArgs args) {
        Point panelOffset = new Point(20, 20);
        for (int i = 0; i < 4; i++) {
            var panel = new CircleButton() {
                Name = "panel" + i, //Attention! You have hidden the property "Name" in "Control" with a re-declaration in "CircleButton"
                Tag = i, //not needed anymore, right?
                Centre = new Point(panelOffset.X + i * 10, panelOffset.Y),
                Radius = 10,
                BackColor = Color.Red,
                Message = "Index: " + i.ToString(),
            };
            panel.Click += (s, e) => {
                panel.Focus();
            };
            panel.PreviewKeyDown += (s, e) => {
                if(e.KeyCode == Keys.Up) {
                    Point centre = panel.Centre; //copy value
                    centre.Y -= 10;
                    panel.Centre = centre; //assign modified copy
                    Invalidate();
                }
                if(e.KeyCode == Keys.Down) {
                    Point centre = panel.Centre; //copy value
                    centre.Y += 10;
                    panel.Centre = centre; //assign modified copy
                    Invalidate();
                }
            };
            myPanels.Add(panel);
            pictureBox1.Controls.Add(panel);
        }
    }
}