0
votes

I borrowed some code to draw a rectangle on an image, e.g. like a selection box. Right now, the code draws a rectangle any time you click and drag your mouse. If you simply left-click without dragging, nothing at all happens - the existing rectangle stays put. If you click and drag a new rectangle, the old rectangle disappears.

That's almost exactly like I want (I'm not wanting to permanently draw on the image... yet...), but with one change: I'd like for a single left-click to make the rectangle disappear as well.

The code is as follows:

public partial class ScreenSelection : Form
{
  private Point RectStartPoint;
  private Rectangle Rect = new Rectangle();
  private Brush selectionBrush = new SolidBrush(Color.FromArgb(128, 72, 145, 220));

  public ScreenSelection(DataTable buttonData)
  {
    InitializeComponent();
  }

  private void Canvas_MouseDown(object sender, MouseEventArgs e)
  {
    if (e.Button == MouseButtons.Left)
    {
      RectStartPoint = e.Location;
      Invalidate();
    }
  }

  private void Canvas_MouseMove(object sender, MouseEventArgs e)
  {
    if (e.Button != MouseButtons.Left)
      return;
    Point tempEndPoint = e.Location;
    Rect.Location = new Point(
        Math.Min(RectStartPoint.X, tempEndPoint.X),
        Math.Min(RectStartPoint.Y, tempEndPoint.Y));
    Rect.Size = new Size(
        Math.Abs(RectStartPoint.X - tempEndPoint.X),
        Math.Abs(RectStartPoint.Y - tempEndPoint.Y));
    Canvas.Invalidate();
  }

  private void Canvas_Paint(object sender, PaintEventArgs e)
  {
    // Draw the rectangle...
    if (Canvas.Image != null)
    {
      if (Rect != null && Rect.Width > 0 && Rect.Height > 0)
      {
        e.Graphics.FillRectangle(selectionBrush, Rect);
      }
    }
  }
}

I also have the user load a bitmap in as the image of the canvas, so once the user does that, canvas.image won't equal null.

so how can I make that rectangle disappear on a left click? I'm already doing an invalidate on the left-click, and that's clearly not getting rid of it.

I tried forcing the rectangle size on a left-click by doing:

        if (e.Button == MouseButtons.Left)
        {
            RectStartPoint = e.Location;
            Rect.Height = 0;
            Rect.Width = 0;
            Invalidate();
        }

and tried Rect.Size, Rect = Rectangle.Empty, Canvas.Refresh()...

How can I accomplish this?

Edit: I've also tried saving the graphics state and restoring it. That doesn't work... (no errors, just not getting rid of the rectangle)

1
Once you splat something on a graphic object, you can't erase it. You have to clear the canvas.LarsTech
@Lars: He is using the Paint event, doesn't he? Solution: Code the MouseUp event and measure the size of the Rectangle. When empty don't redraw. Call invalidate in the MouseUp as well!TaW
@TaW I'm liking where you're going with this... but not sure how to accomplish the phrase "don't redraw".TulsaNewbie
Wait... I think I follow now...TulsaNewbie
Graphics.Save saves not the stuff you draw but changes you make to the Graphics object/tool, like scaling or rotating it. Off to bed now. You may want to look into this post which shows the way I do non-persistent drawing. Not sure what the various parts of your app are you want to put together..TaW

1 Answers

0
votes

Finally found a way to do it where I keep the drawing inside the paint event to improve performance / remove flicker...

It all had to do with fillRectangles

here's the working code:

public partial class ScreenSelection : Form
{
    private Point RectStartPoint;
    private Rectangle Rect = new Rectangle();
    private Brush selectionBrush = new SolidBrush(Color.FromArgb(128, 72, 145, 220));
    private List<Rectangle> Rects = new List<Rectangle>();
    private bool RectStart = false;

    public ScreenSelection(DataTable buttonData)
    {
        InitializeComponent();
    }

   private void Canvas_MouseUp(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            if (RectStartPoint == e.Location)
            {
                int i = Rects.Count;
                if (i > 0) { Rects.RemoveAt(i - 1); }
                Canvas.Refresh();
            }
        }
    }

    private void Canvas_MouseDown(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            RectStartPoint = e.Location;
            int i = Rects.Count;
            if (i >= 1) { Rects.RemoveAt(i - 1); }
            RectStart = false;
            Canvas.Refresh();
        }
    }

    private void Canvas_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button != MouseButtons.Left)
            return;

        Point tempEndPoint = e.Location;
        Rect.Location = new Point(
            Math.Min(RectStartPoint.X, tempEndPoint.X),
            Math.Min(RectStartPoint.Y, tempEndPoint.Y));
        Rect.Size = new Size(
            Math.Abs(RectStartPoint.X - tempEndPoint.X),
            Math.Abs(RectStartPoint.Y - tempEndPoint.Y));
        if (!RectStart)
        {
            Rects.Add(Rect);
            RectStart = true;
        }
        else
        {
            Rects[(Rects.Count - 1)] = Rect;
        }
        Canvas.Invalidate(); 
    }

    private void Canvas_Paint(object sender, PaintEventArgs e)
    {
        // Draw the rectangle...
        if (Canvas.Image != null)
        {
            if (Rects.Count > 0)
            {
                e.Graphics.FillRectangles(selectionBrush, Rects.ToArray());
            }
        }

    }
}

The bonus to this is that if I'm careful, I'll be able to also make some rectangles permanent while removing others.