Question

I am drawing a rectangle, sleeping for a few milliseconds--then I want to clear the rectangle, but I can't figure out how. (The rectangle is sitting over a graphic so I can't simply cover it up with another rectangle)

                graphics.DrawRectangle(p, innerRectangle)
                System.Threading.Thread.Sleep(75)
                Next I want to clear the rectange...
Was it helpful?

Solution

You need to redraw the graphic (or at least the part of it under the rectangle). If this is a picture box or something similar, use Invaldiate() to force a repaint.

OTHER TIPS

If the rectangle is sitting completely over the graphic you should be able to just redraw or refresh the underlying graphic. If it is not, you will need to redraw the rectangle using the background color, and then refresh the underlying graphic.

I guess it should work to copy the original data from the surface into a temporary bitmap before drawing the rectangle, and then draw the bitmap back in place.

Update

There is already an accepted answer, but I thought I could share a code sample anyway. This one draws the given rectangle in red on the given control, and restores the area after 500 ms.

public void ShowRectangleBriefly(Control ctl, Rectangle rect)
{
    Image toRestore = DrawRectangle(ctl, rect);
    ThreadPool.QueueUserWorkItem((WaitCallback)delegate
    {
        Thread.Sleep(500);
        this.Invoke(new Action<Control, Rectangle, Image>(RestoreBackground), ctl, rect, toRestore);
    });
}

private void RestoreBackground(Control ctl, Rectangle rect, Image image)
{
    using (Graphics g = ctl.CreateGraphics())
    {
        g.DrawImage(image, rect.Top, rect.Left, image.Width, image.Height);
    }
    image.Dispose();
}

private Image DrawRectangle(Control ctl, Rectangle rect)
{
    Bitmap tempBmp = new Bitmap(rect.Width + 1, rect.Height + 1);
    using (Graphics g = Graphics.FromImage(tempBmp))
    {
        g.CopyFromScreen(ctl.PointToScreen(new Point(rect.Top, rect.Left)), new Point(0, 0), tempBmp.Size);
    }

    using (Graphics g = this.CreateGraphics())
    {
        g.DrawRectangle(Pens.Red, rect);
    }
    return tempBmp;
}

I had the same problem and resolved it with an extra panel drawn on the main form and shown/hidden, sized and positioned as necessary.

SelectionBox box = new SelectionBox();
box.Location = location;
box.Size = size;
box.Visible = true;

Then when rectangle is not necessary anymore, just hide it by calling:

box.Visible = false;

The panel class is made with transparency to ensure that overlay graphics does not hide other content of the window.

  [System.ComponentModel.DesignerCategory("Code")]
  public class SelectionBox : Panel
  {
    protected override void OnPaint(PaintEventArgs e)
    {
      const int penWidth = 2;
      int offset = penWidth - 1;
      using (Pen pen = new Pen(Color.Red, 2))
        e.Graphics.DrawRectangle(pen, offset, offset, 
          ClientSize.Width - offset - 1, ClientSize.Height - offset - 1);
    }

    protected override CreateParams CreateParams
    {
      get
      {
        CreateParams cp = base.CreateParams;
        cp.ExStyle |= 0x00000020; // WS_EX_TRANSPARENT
        return cp;
      }
    }
  }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top