RAD Studio |  |

Tracking Movement
See Also
Collapse All

The problem with this example as the OnMouseMove event handler is currently written is that it draws the line to the current mouse position from the last mouse position, not from the original position. You can correct this by moving the drawing position to the origin point, then drawing to the current point:

Copy Code

    procedure TForm1.FormMouseMove(Sender: TObject;Button: TMouseButton;
    Shift: TShiftState; X, Y: Integer);
    begin
    if Drawing then
    begin
    Canvas.MoveTo(Origin.X, Origin.Y);{ move pen to starting point }
    Canvas.LineTo(X, Y);
    end;
    end;

Copy Code

    void __fastcall TForm1::FormMouseMove(TObject *Sender, TMouseButton Button,
      TShiftState Shift, int X, int Y)
    {
      if (Drawing)
      {
        Canvas->MoveTo(Origin.x, Origin.y);  // move pen to starting point
        Canvas->LineTo(X, Y);
      }
    }

The above tracks the current mouse position, but the intermediate lines do not go away, so you can hardly see the final line. The example needs to erase each line before drawing the next one, by keeping track of where the previous one was. The MovePt field allows you to do this.

MovePt must be set to the endpoint of each intermediate line, so you can use MovePt and Origin to erase that line the next time a line is drawn:

Copy Code

    procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
    Shift: TShiftState; X, Y: Integer);
    begin
    Drawing := True;
    Canvas.MoveTo(X, Y);
    Origin := Point(X, Y);
    MovePt := Point(X, Y);{ keep track of where this move was }
    end;
    procedure TForm1.FormMouseMove(Sender: TObject;Button: TMouseButton;
    Shift: TShiftState; X, Y: Integer);
    begin
    if Drawing then
    begin
    Canvas.Pen.Mode := pmNotXor;{ use XOR mode to draw/erase }
    Canvas.MoveTo(Origin.X, Origin.Y);{ move pen back to origin }
    Canvas.LineTo(MovePt.X, MovePt.Y);{ erase the old line }
    Canvas.MoveTo(Origin.X, Origin.Y);{ start at origin again }
    Canvas.LineTo(X, Y);{ draw the new line }
    end;
    MovePt := Point(X, Y);{ record point for next move }
    Canvas.Pen.Mode := pmCopy;
    end;

Copy Code

    void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,
      TShiftState Shift, int X, int Y)
    {
      Drawing = true;            // set the Drawing flag
      Canvas->MoveTo(X, Y);      // set pen position
      Origin = Point(X, Y);      // record where the line starts
      MovePt = Point(X, Y);      // record last endpoint
    }
    void __fastcall TForm1::FormMouseMove(TObject *Sender, TMouseButton Button,
      TShiftState Shift, int X, int Y)
    {
      if (Drawing)
      {
        Canvas->Pen->Mode = pmNotXor;        // use XOR mode to draw/erase
        Canvas->MoveTo(Origin.x, Origin.y);  // move pen to starting point
        Canvas->LineTo(MovePt.x, MovePt.y);  // erase old line
        Canvas->MoveTo(Origin.x, Origin.y);  // move pen to starting point again
        Canvas->LineTo(X, Y);                // draw new line
      }
      MovePt = Point(X, Y);      // record new endpoint
      Canvas->Pen->Mode = pmCopy;
    }

Now you get a "rubber band" effect when you draw the line. By changing the pen's mode to pmNotXor, you have it combine your line with the background pixels. When you go to erase the line, you're actually setting the pixels back to the way they were. By changing the pen mode back to pmCopy (its default value) after drawing the lines, you ensure that the pen is ready to do its final drawing when you release the mouse button.

See Also

Tracking the Origin Point

Copyright(C) 2009 Embarcadero Technologies, Inc. All Rights Reserved.
What do you think about this topic? Send feedback!