delphitcanvas

How delete a rectangle created with Canvas?


I have a rectangle that is drawed in a TPaintBox component using my mouse. So, how delete this rectangle (totaly) from my application after "mouse up event" of TPaintBox?

enter image description here

Any suggestion will welcome.

Here is my code that draw this rectangle:

private
    FSelecting: Boolean;
    FSelection: TRect;
  end;

procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  FSelection.Left := X;
  FSelection.Top := Y;
  FSelecting := True;
end;

procedure TForm1.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if FSelecting then
  begin
    FSelection.Right := X;
    FSelection.Bottom := Y;
    PaintBox1.Invalidate;
  end;
end;

procedure TForm1.PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  FSelecting := False;
  FSelection.Right := X;
  FSelection.Bottom := Y;
  PaintBox1.Invalidate;
end;

procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
  PaintBox1.Canvas.Brush.Color := clRed;
  PaintBox1.Canvas.Rectangle(FSelection);
end;

Solution

  • You can't delete a drawing, you have to draw something else over top of it.

    In the code you have shown, you can simply set FSelection to an empty 0x0 rectangle and Invalidate() the PaintBox again. Its normal picture will be drawn, and you won't draw a rectangle on top of it.

    procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    begin
      if Button = mbLeft then
      begin
        FSelection := Rect(X, Y, X, Y);
        FSelecting := True;
      end;
    end;
    
    procedure TForm1.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    begin
      if FSelecting then
      begin
        FSelection.Right := X;
        FSelection.Bottom := Y;
        PaintBox1.Invalidate;
      end;
    end;
    
    procedure TForm1.PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    begin
      if (Button = mbLeft) and FSelecting then
      begin
        FSelecting := False;
        FSelection := Rect(0, 0, 0, 0);
        PaintBox1.Invalidate;
      end;
    end;
    
    procedure TForm1.PaintBox1Paint(Sender: TObject);
    begin
      //...
      PaintBox1.Canvas.Brush.Color := clRed;
      PaintBox1.Canvas.Rectangle(FSelection);
    end;
    

    Or, assuming you need to remember the selected rectangle for use with other things, then simply don't draw the selected rectangle onto the PaintBox when FSelecting is false.

    procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    begin
      if Button = mbLeft then
      begin
        FSelection := Rect(X, Y, X, Y);
        FSelecting := True;
      end;
    end;
    
    procedure TForm1.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    begin
      if FSelecting then
      begin
        FSelection.Right := X;
        FSelection.Bottom := Y;
        PaintBox1.Invalidate;
      end;
    end;
    
    procedure TForm1.PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    begin
      if (Button = mbLeft) and FSelecting then
      begin
        FSelecting := False;
        PaintBox1.Invalidate;
      end;
    end;
    
    procedure TForm1.PaintBox1Paint(Sender: TObject);
    begin
      //...
      if FSelecting then
      begin
        PaintBox1.Canvas.Brush.Color := clRed;
        PaintBox1.Canvas.Rectangle(FSelection);
      end;
    end;
    

    Either way, for good measure, you should draw the rectangle transparent with a dotted border so the user can see what they are selecting without being too intrusive:

    procedure TForm1.PaintBox1Paint(Sender: TObject);
    begin
      //...
      if FSelecting then
      begin
        PaintBox1.Canvas.Brush.Style := bsClear;
        PaintBox1.Canvas.Pen.Style := psDot;
        PaintBox1.Canvas.Rectangle(FSelection);
      end;
    end;