C# перетаскивание элементов управления по панели


Я разрабатываю систему, которая позволяет пользователю перетаскивать объекты в пределах одной панели, я провел некоторые исследования и обнаружил, что я должен использовать события мыши, такие как mouse_up, mouse_down и mouse_move.

Программа сгенерирует 3 picturebox и позволит пользователю перетаскивать каждый picturebox в пределах панели, но программа, которую я кодирую, не работает идеально, так как когда я перетаскиваю picturebox, picturebox будет двигаться, но не в соответствии с моим местоположением курсора мыши, это невозможно. где-то еще, кроме того, при перетаскивании, есть тени picturebox в панели, я пробовал эти update(),refresh () и invalidate (), но это кажется мне не полезным. Ниже приведены мои коды, спасибо за помощь

public partial class Form1 : Form
{

    List<PictureBox> pictureBoxList = new List<PictureBox>();
    private bool isDragging = false;

    public Form1()
    {
        InitializeComponent();

        for (int i = 0; i < 3; i++)
        {
            PictureBox picture = new PictureBox
            {
                Name = "pictureBox" + i,
                Size = new Size(20, 20),
                Location = new Point(i * 40, i * 40),
                BorderStyle = BorderStyle.FixedSingle,
                SizeMode = PictureBoxSizeMode.Zoom,
                ImageLocation = "A.jpg"
            };
            pictureBoxList.Add(picture);


            foreach (PictureBox p in pictureBoxList)
            {
                p.MouseDown += new MouseEventHandler(c_MouseDown);
                p.MouseMove += new MouseEventHandler(c_MouseMove);
                p.MouseUp += new MouseEventHandler(c_MouseUp);
                pnlDisplayImage.Controls.Add(p);
                pnlDisplayImage.Refresh();
            }
        }
    }


    void c_MouseDown(object sender, MouseEventArgs e)
    {
        isDragging = true;
    }

    void c_MouseMove(object sender, MouseEventArgs e)
    {

        if (isDragging == true) {
            Control c = sender as Control;
            for (int i = 0; i < pictureBoxList.Count(); i++)
            {
                if (c.Equals(pictureBoxList[i]))
                {
                    pictureBoxList[i].Location = new Point(e.X, e.Y);
                }
            }
        }
    }

    void c_MouseUp(object sender, MouseEventArgs e)
    {
        PictureBox c = sender as PictureBox;
        isDragging = false;
        for (int i = 0; i < pictureBoxList.Count(); i++) { 
            if (c.Equals(pictureBoxList[i])){
                pictureBoxList[i].Location = new Point(e.X, e.Y);
            }
        }
    }

    private void pnlDisplayImage_Paint(object sender, PaintEventArgs e)
    {
        foreach (PictureBox p in pictureBoxList)
        {
            pnlDisplayImage.Controls.Add(p);
        }
    }

}
2 3

2 ответа:

Наконец-то я нашел, какие проблемы привели к тому, что моя программа не работает так, как я ожидал. Основная проблема заключается в том, что я случайно поместил цикл foreach в цикл for, который я использовал для создания pictureBox, эта проблема вызвала pictureBox выходит некоторые тени эффект при перетаскивании во время выполнения из-за Есть несколько же pictureBox. Кроме того, я немного изменил коды, и теперь он работает так, как я ожидал. Ниже приведен код, который я хочу получить для ответа.

public partial class Form1 : Form
{

    List<PictureBox> pictureBoxList = new List<PictureBox>();
    private bool isDragging = false;
    Point move;

    public Form1()
    {
        InitializeComponent();

        for (int i = 0; i < 3; i++)
        {
            PictureBox picture = new PictureBox
            {
                Name = "pictureBox" + i,
                Size = new Size(20, 20),
                Location = new Point(i * 40, i * 40),
                BorderStyle = BorderStyle.FixedSingle,
                SizeMode = PictureBoxSizeMode.Zoom,
                ImageLocation = "A.jpg"
            };
            pictureBoxList.Add(picture);
        }

        foreach (PictureBox p in pictureBoxList)
        {
                p.MouseDown += new MouseEventHandler(c_MouseDown);
                p.MouseMove += new MouseEventHandler(c_MouseMove);
                p.MouseUp += new MouseEventHandler(c_MouseUp);
                pnlDisplayImage.Controls.Add(p);
                pnlDisplayImage.Refresh();
         }

    }

    void c_MouseDown(object sender, MouseEventArgs e)
    {
        Control c = sender as Control;
        isDragging = true;
        move = e.Location;
    }

    void c_MouseMove(object sender, MouseEventArgs e)
    {

        if (isDragging == true) {
            Control c = sender as Control;
            for (int i = 0; i < pictureBoxList.Count(); i++)
            {
                if (c.Equals(pictureBoxList[i]))
                {
                    pictureBoxList[i].Left += e.X - move.X;
                    pictureBoxList[i].Top += e.Y - move.Y;
                }
            }
        }
    }

    void c_MouseUp(object sender, MouseEventArgs e)
    {
        isDragging = false;
    }
}

Попробуйте что-то вроде (это пользовательский элемент управления с переопределениями, но его должно быть легко преобразовать в события):

    private bool _isMoved = false;  // true if move mode on
    private Point _pointMove = new Point(0);    // for moving

    protected override void OnMouseDown(MouseEventArgs e)
    {
        // if left button pressed
        if(e.Button == MouseButtons.Left) 
        {
            _pointMove.X = e.X;
            _pointMove.Y = e.Y;
            _isMoved = true;
            Cursor = Cursors.SizeAll;
            Capture = true;
        }
        base.OnMouseDown (e);
    }

    protected override void OnMouseUp(MouseEventArgs e)
    {
        // if move mode on
        if(_isMoved) 
        {
            _isMoved = false;
            Cursor = Cursors.Default;
            Capture = false;
        }
        base.OnMouseUp (e);
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        // if move mode on
        if (_isMoved)
        {
            Left += e.X - _pointMove.X;
            Top += e.Y - _pointMove.Y;
        }
        base.OnMouseMove (e);
    }