views:

127

answers:

3

Hi guys,

I'm trying to draw a single line using OnMouseMove() event. My Problem is that everytime I move the mouse It leaves a trail. I tried to use the refresh method, but when I stop moving the mouse the line is gone. I don't want the line to be drawn OnPaint();, Just want to draw it OnMouseMove().

EDIT: I'm using a transparent panel(cp.ExStyle |= 0x20;), so I cant use the graphics.Clear() and BackColor()

Here's a Sample Image without the Refresh():

alt text

Here's my code:

private void panel1_MouseMove(object sender, MouseEventArgs e)
{  
   Graphics g = panel1.CreateGraphics();

   g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
   using (var p = new Pen(Color.Black, 3))
   {
      p.StartCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
      p.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;

      g.DrawLine(p, st, e.Location);
   }
   Thread.Sleep(30);
   Invalidate();
   //this.Refresh();

   g.Dispose();
}

Regards

A: 

The problem with the line disappearing is that when the panel is repainted, the line is not redrawn. What you really need is to update the end-point of the line-segment when the mouse is moved across the panel and to invalidate the panel. Of course, this will mean that you do handle the Paint event on the panel.

Code here, without the event-handler registration:

Point endPoint;

private void panel1_Paint(object sender, PaintEventArgs e)
{
    Graphics g = e.Graphics;
    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

    using (var p = new Pen(Color.Black, 3))
    {
        p.StartCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
        p.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;

        g.DrawLine(p, st, endPoint);
    }

    Thread.Sleep(30);
}

private void panel1_MouseMove(object sender, MouseEventArgs e)
{
    endPoint = e.Location;
    panel1.Invalidate();
}
Ani
the g.Clear() is good. But i forgot to include there that I override a panel user control with CreateParams. So the panel is set to transparent. that's why I cant use the g.Clear();
Rye
@Rye: Alright. But why can't you handle the `Paint` event? That's the easiest way.
Ani
I just want the line as a marker.
Rye
@Rye: Can you explain what that means?
Ani
I have a transparent Panel. It is positioned above an image(e.g picturebox), This image contains line drawings. I just want to measure the drawings using the drawline on `MouseMove()` event.
Rye
A: 

After

g.DrawLine(p, st, e.Location); 

put:

st = e.Location;

Does that fix the problem?

BoltBait
Nope, It just creates new line.
Rye
Oh, right. I thought you were trying to draw like a pencil. I see now that you want to have a single starting place and be able to move the end point around having it redraw only a single line between the start point and the new end point.
BoltBait
Yes @BoltBait thats correct.
Rye
A: 

The following works for me. Basically keep track of the last line drawn and draw over it with the background color of the panel (gives the effect of clearing it).

   public partial class Form1 : Form
   {
      public Form1()
      {
         InitializeComponent();
      }

      private const int PEN_WIDTH = 3;
      private const LineCap START_CAP = LineCap.ArrowAnchor;
      private const LineCap END_CAP = LineCap.ArrowAnchor;
      Point mAnchorPoint = new Point(10, 10);
      Point mPreviousPoint = Point.Empty;

      private void panel1_MouseMove(object sender, MouseEventArgs e)
      {
         using (Graphics g = panel1.CreateGraphics())
         {
            // Clear last line drawn
            using (Pen clear_pen = new Pen(panel1.BackColor, PEN_WIDTH))
            {
               clear_pen.StartCap = START_CAP;
               clear_pen.EndCap = END_CAP;
               g.DrawLine(clear_pen, mAnchorPoint, mPreviousPoint);
            }

            // Update previous point
            mPreviousPoint = e.Location;

            // Draw the new line
            using (Pen draw_pen = new Pen(Color.Black, PEN_WIDTH))
            {
               draw_pen.StartCap = START_CAP;
               draw_pen.EndCap = END_CAP;
               g.DrawLine(draw_pen, mAnchorPoint, e.Location);
            }
         }
      }
   }

If you panel's background color is set to Transparent, you will need to change panel1.BackColor to panel1.Parent.BackColor

If the Transparent Panel is not working, you could use the DrawReversibleLine function (although this doesn't allow the color or thickness of the line to be changed, it should have no issues with drawing/erasing even if the panel is Transparent:

  Point mAnchorPoint = new Point(200, 200);
  Point mPreviousPoint = Point.Empty;

  private void panel1_MouseMove(object sender, MouseEventArgs e)
  {
     if (mPreviousPoint != Point.Empty)
     {
        // Clear last line drawn
        ControlPaint.DrawReversibleLine(PointToScreen(mAnchorPoint), PointToScreen(mPreviousPoint), Color.Pink);
     }

     // Update previous point
     mPreviousPoint = e.Location;
     mPreviousPoint.Offset(myPanel1.Location);

     // Draw the new line
     ControlPaint.DrawReversibleLine(PointToScreen(mAnchorPoint), PointToScreen(mPreviousPoint), Color.Pink);
  }
SwDevMan81
ah yes, this will work fine. But I'm using a transparent panel(CreateParams.ExStyle |= 0x20;).
Rye
I just saw your comments. You can use `panel1.Parent.BackColor`
SwDevMan81
panel1's parent is the form. The transparent panel is flickering to white. when i used `panel1.Parent.BackColor`
Rye
@Rye - Updated my answer with a different approach
SwDevMan81
@SwDev Oh! yes the drawreversible line. I forgot. Wait i'll try.
Rye
You save the day @SwDevMan81. I forgot that theres a `DrawReversibleLine()` method. Thanks much!
Rye
No prob, glad I could help
SwDevMan81