1

I've come across a problem in my panel1_MouseMove event. I have 3 pictureboxes inside List pBoxes, which are all drawn to the panel & the picturebox controls are set to Visible = false.

The problem is that when there are overlapping images, when I click one image it may select the pictureBox Behind it. Like soenter image description here

Here is the code:

    private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if (picturebox1.Bounds.Contains(e.Location) && !picturebox1.Visible)
{
picturebox1.Show();
picturebox2.Hide();
picturebox3.Hide();
}
if (picturebox2.Bounds.Contains(e.Location) && !picturebox2.Visible)
{
picturebox1.Hide();
picturebox2.Show();
picturebox3.Hide();
}
if (picturebox3.Bounds.Contains(e.Location) && !picturebox3.Visible)
{
picturebox1.Hide();
picturebox2.Hide();
picturebox3.Show();
}

Any help would be gladly appreciated, and yes I have to use Bounds.Contains for my particular application. Another way to look at my question is that I am trying to create a pictureBox1__MouseClick event without a Visible control.

4

1 回答 1

1

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.

于 2012-08-08T19:48:49.497 回答