Link to home
Start Free TrialLog in
Avatar of roosiedb
roosiedb

asked on

Erase a line from canvas?

Help me please !!!

I want to draw a line from Shape1 to Shape2 (just simple, OK).

When I drag Shape1 or Shape2 to another position, the line need to be changed also. I guess that I'll need to erase the line before I draw the "new" line on the canvas...?

This all sounds very simple, but now the problem I stick with:

When I have a background-picture, I am not able to erase lines without damage the background-picture. Please tell me how to fix this...

Greetz,
Jan van Barchum.
Avatar of philipleighs
philipleighs

Call InvalidateRect passing a TRect describing the area you want to refresh.

Then in the OnPaint event, redraw the area.

Either that or you could xor the line when you initially draw it. Then to undraw it, you just xor the line again!
ie. to draw a line in xor mode:
Canvas.PenMode = pmXOR;
Canvas.MoveTo(x1, y1);
Canvas.LineTo(x2, y2);

Now to undraw the line, call the exact three lines.

Cheers,
Phil.
Phil is right, in particular the second way is quite common (and usually refered as "rubber banding"). There's a drawback, though, as the color of the drawn line is not constant (as each pixel of the line is the inverse of the underlying pixel). If you want to avoid this you are probably better off with a memory bitmap which is constructed from your background image and the other graphic elements and which you would then blit to the target canvas. This should be fast enough on today's machines.

Ciao, Mike
Try the commands REPAINT or REFRESH.

Aaaaargh...
Avatar of kretzschmar
hi friends,

have done a little workaround
includes all suggestions, which done

unit shapes_u;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, StdCtrls;

type
  TForm1 = class(TForm)
    Shape1: TShape;
    Shape2: TShape;
    Image1: TImage;  //a image as background, align = alclient
    Button1: TButton;
    procedure Shape1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure Shape1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure Shape1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

Type
  TLine = Record
            LineBegin : TPoint;
            LineEnd   : TPoint;
          end;

var xx,yy : Integer;
    M : TPenMode;
    R : Trect;
    L : TLine;


//Calculates the shortest line from the sides
Function CalculateLine(T1,T2 : TControl) : TLine;
Var
  Points : Array[1..2,1..4] of TPoint;
  i,j,ii,jj : Integer;
  LineLen : Double;
begin
  Points[1,1] := Point(t1.left + (t1.width div 2),t1.Top - 1);
  Points[1,2] := Point(t1.left + t1.width + 1, t1.top + (t1.Height div 2));
  Points[1,3] := Point(t1.left + (t1.width div 2), t1.top + t1.Height + 1);
  Points[1,4] := Point(t1.Left - 1, t1.top + (t1.Height div 2));

  Points[2,1] := Point(t2.left + (t2.width div 2),t2.Top - 1);
  Points[2,2] := Point(t2.left + t2.width + 1, t2.top + (t2.Height div 2));
  Points[2,3] := Point(t2.left + (t2.width div 2), t2.top + t2.Height + 1);
  Points[2,4] := Point(t2.Left - 1, t2.top + (t2.Height div 2));
  LineLen := MaxLongint;
  for i := 1 to 4 do
    for J := 1 to 4 do
      If LineLen > Sqrt(Sqr(Points[1,i].x - Points[2,j].x)+Sqr(Points[1,i].y - Points[2,j].y)) then
      begin
        LineLen := Sqrt(Sqr(Points[1,i].x - Points[2,j].x)+Sqr(Points[1,i].y - Points[2,j].y));
        ii := i;
        jj := j;
      end;
  Result.LineBegin := Points[1,ii];
  Result.LineEnd   := Points[2,jj];
end;

//Draws a line
Procedure DrawLine(A,B : TPoint);
begin
  M := Form1.Canvas.Pen.Mode;
  Form1.Canvas.Pen.Mode := pmNotXor;
  Form1.Canvas.MoveTo(A.x,A.y);
  Form1.Canvas.LineTo(B.x,B.y);
  Form1.Canvas.Pen.Mode := M;
end;

//is also assigned to shape2
procedure TForm1.Shape1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if ssleft in shift then
  begin
    If Sender is TShape then
    begin
      L := CalculateLine(Shape1,Shape2);
      DrawLine(L.LineBegin,L.LineEnd);
      TShape(Sender).Top := TShape(Sender).Top+y-yy;
      TShape(Sender).left := TShape(Sender).left+x-xx;
      L := CalculateLine(Shape1,Shape2);
      DrawLine(L.LineBegin,L.LineEnd);
    end;
  end;
end;

//is also assigned to shape2
procedure TForm1.Shape1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if Button = mbleft then
  begin
    xx := x;
    yy := y;
  end;
end;

//is also assigned to shape2
procedure TForm1.Shape1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if button = mbleft then
  begin
    Refresh;  //Repaints
    Button1.Click;
  end;
end;

//Draws or erase a line
procedure TForm1.Button1Click(Sender: TObject);
begin
  L := CalculateLine(Shape1,Shape2);
  DrawLine(L.LineBegin,L.LineEnd);
end;

end.

have fun

meikl

Avatar of roosiedb

ASKER

There was no answer included in your message (vuile hond) !!
hi roosiedb,

evaluate my sample above

meikl


Hello Kretzschmar,

Your program helped me a lot. It works perfectly...
Tell me how I can send the credits to your account?

Greetz,
Jan van Barchum.
ASKER CERTIFIED SOLUTION
Avatar of kretzschmar
kretzschmar
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial