BigONotation
BigONotation

Reputation: 4538

How to draw a rectangle around a TImage when it is selected

I have a set of TImage instances layed out on a panel. The TImages represent icons (see attached screenshot). I would like to draw a red rectangle around a given TImage instance when the user selects it by clicking on it. Not sure how to proceed...

Edit: why am I not using a TToolbar? Reason 1: I don't like the default "look and feel" of the TToolbar and I want to have more control on it. Reason 2: This control is not really a TToolbar. It should rather be considered as a sort of "bookmark" element, which displays different text in the memo field depending on which "bookmark" is selected.

enter image description here

The accepted solution using Remy Lebeau's suggestion is shown below:

enter image description here

Upvotes: 2

Views: 6996

Answers (3)

Dodek Tusk
Dodek Tusk

Reputation: 11

I would modify the proposals. there would be no problem with the objects on the form type the following :

TImage = class(ExtCtrls.TImage)
  private
    FShowRectangle: Boolean;
    procedure SetShowRectangle(Value: Boolean);
  protected
    procedure Paint; override;
  public
    property ShowRectangle: Boolean read FShowRectangle write SetShowRectangle;
  end;

Upvotes: 1

Remy Lebeau
Remy Lebeau

Reputation: 595971

I would suggest using a TPaintBox instead of a TImage. Load your image into an appropriate TGraphic class (TBitmap, TIcon, TPNGImage, etc) and then draw it onto the TPaintBox in its OnPaint event. That is all a TImage really does (it holds a TGraphic that is drawn onto its Canvas when painted). You can then draw a red rectangle on top of the image when needed. For example:

procedure TMyForm.PaintBox1Click(Sender: TObject);
begin
  PaintBox1.Tag := 1;
  PaintBox1.Invalidate;
  PaintBox2.Tag := 0;
  PaintBox2.Invalidate;
end;

procedure TMyForm.PaintBox2Click(Sender: TObject);
begin
  PaintBox1.Tag := 0;
  PaintBox1.Invalidate;
  PaintBox2.Tag := 1;
  PaintBox2.Invalidate;
end;

procedure TMyForm.PaintBox1Paint(Sender: TObject);
begin
  PaintBox1.Canvas.Draw(MyImage1, 0, 0);
  if PaintBox1.Tag = 1 then
  begin
    PaintBox1.Canvas.Brush.Style := bsClear;
    PaintBox1.Canvas.Pen.Color := clRed;
    PaintBox1.Canvas.Rectangle(PaintBox1.ClientRect);
  end;
end;

procedure TMyForm.PaintBox2Paint(Sender: TObject);
begin
  PaintBox2.Canvas.Draw(MyImage2, 0, 0);
  if PaintBox2.Tag = 1 then
  begin
    PaintBox2.Canvas.Brush.Style := bsClear;
    PaintBox2.Canvas.Pen.Color := clRed;
    PaintBox2.Canvas.Rectangle(PaintBox2.ClientRect);
  end;
end;

Alternatively, you can derive a new class from TImage and override its virtual Paint() method to draw the rectangle after default drawing. For example:

type
  TMyImage = class(TImage)
  private
    FShowRectangle: Boolean;
    procedure SetShowRectangle(Value: Boolean);
  protected
    procedure Paint; override;
  public
    property ShowRectangle: Boolean read FShowRectangle write SetShowRectangle;
  end;

procedure TMyImage.SetShowRectangle(Value: Boolean);
begin
  if FShowRectangle <> Value then
  begin
    FShowRectangle := Value;
    Invalidate;
  end;
end;

type
  TGraphicControlAccess = class(TGraphicControl)
  end;

procedure TMyImage.Paint;
begin
  inherited;
  if FShowRectangle then
  begin
    with TGraphicControlAccess(Self).Canvas do
    begin
      Brush.Style := bsClear;
      Pen.Color := clRed;
      Rectangle(ClientRect);
    end;
  end;
end;

procedure TMyForm.MyImage1Click(Sender: TObject);
begin
  MyImage1.ShowRectangle := true;
  MyImage2.ShowRectangle := false;
end;

procedure TMyForm.MyImage2Click(Sender: TObject);
begin
  MyImage1.ShowRectangle := false;
  MyImage2.ShowRectangle := true;
end;

Upvotes: 9

Edward
Edward

Reputation: 277

I would recommend using a TRectangle. You can add an bitmap (bitmap, jpg, etc) via the Fill propery and set the Stroke property for the border.

You also can set the xRadius and yRadius properties for rounded borders.

Upvotes: -1

Related Questions