How to delete (clear) lines

  • Thread starter Thread starter Tomomichi Amano
  • Start date Start date
T

Tomomichi Amano

Hello

How can I delete (clear) lines that were made useing Graphics.DrawLine() ?

Thanks in advance! Have a nice day!
 
In VS 6.0 and in OpenGL, this is fairly simple, you just use the XOR
drawing mode, which draws a line normally the first time, and then
"erases" it the second time.

GDI+ doesn't have support for the pen modes anymore, but your task is
not too much more difficult.

There are a couple ways to do this:

1. you could keep a bitmap of what the clear, or erased state looks
like, and whenever you want to erase the line, you would do something like:


//...
private Image savedImage;
//...

// your standard paint method
private void My_Paint(object sender,
System.Windows.Forms.PaintEventArgs e)
{
if (something_has_changed_like_the_form_has_been_resized)
{
Rectangle rect = this.GetDrawingRectangle();
this.savedImage = new Bitmap(rect.Width, rect.Height);
Graphics gx = Graphics.FromImage(savedImage);
gx.Clear(this.BackColor);

// draw the normal, erased state
// ...
gx.Dispose();
}

Graphics g = e.Graphics;
g.DrawImageUnscaled(this.savedImage,0,0);

// now draw any of the lines, pictures, etc.
// that you want to be erased.
}


2. The previous method is good if you need to completely redraw every
element of your picture each time, but what if you have a bunch of lines
already drawn, and you only want to erase one of them? Here's where you
can use a TextureBrush as a sort of eraser.

//...
private Image lastImage;
private Brush eraserBrush;
//...

// your standard paint method
private void My_Paint(object sender,
System.Windows.Forms.PaintEventArgs e)
{
if (something_has_changed_like_the_form_has_been_resized)
{
// we may need to redraw everything...
Rectangle rect = this.GetDrawingRectangle();
this.lastImage = new Bitmap(rect.Width, rect.Height);
Graphics gx = Graphics.FromImage(this.lastImage);
gx.Clear(this.BackColor);

// draw the normal, erased state
// ...
// draw all of the elements that should be drawn...
gx.Dispose();
this.eraserBrush = new TextureBrush(this.lastImage);
}

// all of our lines, pictures, etc. are already stored
// inside lastImage, so we don't need to do anything here.

// let's say we kept track of some coordinates for a line,
// and also kept track of whether or not we need to do
// some erasing
if (bLineNeedsErasing)
{
// by drawing to this Graphics object, we're updating the
// bitmap image.
Graphics imageGraphics = Graphics.FromImage(this.lastImage);

// assuming the first line was drawn with a width of 1 (float)
Pen p = new Pen(this.eraserBrush, 1F);

// assuming we kept track of a couple System.Drawing.PointF
// points representing the ends of the line
imageGraphics.DrawLine(p, this.linePoint1, this.linePoint2);
imageGraphics.Dispose();
}

Graphics g = e.Graphics;
g.DrawImageUnscaled(this.lastImage,0,0);
}


This second way is almost always the better way to go.

One last note: you're going to notice the screen flickering if you're
doing any kind of drawing. To alleviate this, look up the SetStyle
method, and use something like:

this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.DoubleBuffer, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);

in your own initialization code.
 
Another option is to keep track of everything as you paint it in some sort
of collection, then have an engine that can paint all of those to the
picturebox / form /bitmap whatever. To erase a line, you remove it from the
collection, and repaint everything else. I suppose this could be slow if
there are a lot of lines (and you'll want to use the anti-flicker methods
that Ben listed)

Another option to look at is the ControlPaint class - there is a method
DrawReversibleLine. I haven't used it before, but you can surely find some
examples.
 
Back
Top