You can try something like this. I added three overlapping PictureBoxes with three different background colors for testing.
Initial form setup:
private bool isDragging = false;
private Point dragOffset = Point.Empty;
private PictureBox dragBox;
public Form1() {
InitializeComponent();
panel1.MouseDown += new MouseEventHandler(panel1_MouseDown);
panel1.MouseMove += new MouseEventHandler(panel1_MouseMove);
panel1.MouseUp += new MouseEventHandler(panel1_MouseUp);
panel1.Paint += new PaintEventHandler(panel1_Paint);
panel1.DragEnter += new DragEventHandler(panel1_DragEnter);
panel1.DragDrop += new DragEventHandler(panel1_DragDrop);
}
Drag Drop Events:
void panel1_DragDrop(object sender, DragEventArgs e) {
dragBox.Location = panel1.PointToClient(
new Point(e.X - dragOffset.X, e.Y - dragOffset.Y));
panel1_MouseUp(null, null);
}
void panel1_DragEnter(object sender, DragEventArgs e) {
e.Effect = DragDropEffects.Move;
}
Mouse Events:
void panel1_MouseMove(object sender, MouseEventArgs e) {
if (dragBox != null && !isDragging) {
isDragging = true;
panel1.DoDragDrop(dragBox, DragDropEffects.Move);
}
}
void panel1_MouseDown(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
foreach (PictureBox pb in panel1.Controls.OfType<PictureBox>()
.OrderBy(x => panel1.Controls.GetChildIndex(x))) {
if (pb.Bounds.Contains(e.Location)) {
pb.BringToFront();
pb.Visible = true;
dragBox = pb;
dragOffset = new Point(e.X - pb.Left, e.Y - pb.Top);
panel1.Invalidate();
break;
}
}
}
}
void panel1_MouseUp(object sender, MouseEventArgs e) {
foreach (PictureBox pb in panel1.Controls.OfType<PictureBox>()) {
pb.Visible = false;
}
dragBox = null;
isDragging = false;
}
Paint event:
void panel1_Paint(object sender, PaintEventArgs e) {
foreach (PictureBox pb in panel1.Controls.OfType<PictureBox>()
.OrderByDescending(x => panel1.Controls.GetChildIndex(x))) {
e.Graphics.FillRectangle(new SolidBrush(pb.BackColor), pb.Bounds);
}
}
It uses GetChildIndex
of the parent panel to get the highest PictureBox control inside the panel, and if it finds it, makes the "clicked" one visible and to the front so the Child Index is updated.
Since the PictureBoxes are always hidden (unless dragged), this code will bring the correct PictureBox to the front. I added my paint event that draws the PictureBoxes in reverse order so that the highest box is painted last.
Changed the code to show the selected PictureBox on the MouseDown and then hide it again on the MouseUp.
Added drag and drop code.