4

I need a clickable control that I can tailor to my needs. From the Delphi docs I gathered that a TRectangle would do. I need to create my TRectangles programmatically, so I created a Form, a Panel and a Button (see code below). As TRectangle is derived via TShape from TControl I tested whether I could draw on the TRectangle Canvas using PaintTo, using its own canvas. The TRectF I constructed was created on the assumption that the painting would be relative to the TRectangle's Canvas, so an offset of (0, 0) was needed. The rectangle however is painted at position (0, 0) of the Form! Without paying heed to the changes in the Fill and Stroke properties I made.

I next tried a FillRect and again the same results, although with the correct Fill. Though the call is from a Trectangle variable.Canvas.FillRect, It is always relative to the highest parent in the tree, bypassing TRectangle and TPanel. I always thought that painting is relative to the coordinates of the TControl a Canvas is part of.

Is this wrong or is there something special with TRectangle? Is there a better way of painting on a TRectangle?

unit rect_test_main;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
  FMX.Objects;

type
   TForm1 = class(TForm)
    Panel1: TPanel;
    Button1: TButton;

    procedure Button1Click (Sender: TObject);
    procedure FormCreate (Sender: TObject);

   protected
      FR: TRectangle;

   public
      procedure draw_paintto (rect: TRectangle);
      procedure draw_rect (rect: TRectangle);
      procedure draw_fill (rect: TRectangle);
      procedure draw (surface: TControl);
   end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.FormCreate (Sender: TObject);
begin
   FR := Trectangle.Create (Panel1);
   FR.Parent := Panel1;
   FR.Canvas.BeginScene;
   FR.Canvas.Fill.Color := TAlphaColors.Black;
   FR.Canvas.Stroke.Color := TAlphaColors.Green;
   FR.SetBounds (200, 200, 50, 300);
   FR.OnClick := Button1Click;
   FR.Canvas.EndScene;
end; // FormCreate //

procedure TForm1.Button1Click (Sender: TObject);
begin
   draw_fill (FR);
end;

procedure TForm1.draw_paintto (rect: TRectangle);
var
   r: TRectF;
begin
   FR.Canvas.BeginScene;
   FR.Canvas.Fill.Color := TAlphaColors.Black;
   FR.Canvas.Stroke.Color := TAlphaColors.Green;
   FR.Canvas.Stroke.Thickness := 10;
   r := rect.ShapeRect;
//   r := TRectF.Create (TPointF.Create (FR.Position.X - 10, FR.Position.Y - 10), FR.Width, FR.Height);
   FR.PaintTo (FR.Canvas, r, FR.Parent);
   FR.Canvas.EndScene;
end; // draw_paintto //

procedure TForm1.draw_fill (rect: TRectangle);
var
   r: TRectF;
begin
   FR.Canvas.BeginScene;
   FR.Canvas.Fill.Color := TAlphaColors.Black;
   FR.Canvas.Stroke.Color := TAlphaColors.Green;
   FR.Canvas.Stroke.Thickness := 10;
   r := TRectF.Create (TPointF.Create (FR.Position.X, FR.Position.Y), FR.Width, FR.Height);
   FR.Canvas.FillRect (r, 0, 0, AllCorners, 1);
   FR.Canvas.EndScene;
end; // draw_fill //
Arioch 'The
  • 15,799
  • 35
  • 62
Arnold
  • 4,578
  • 6
  • 52
  • 91

1 Answers1

3

When drawing on a TRectangle one should access the brush and stroke changes on the TRectangle level and not on the Canvas. In this case all works as expected, the Canvas of the TRectangle is drawn.

Key: TRectangle;
...
Key.Fill.Color := TAlphaColors.White;
Key.Fill.Kind := TBrushKind.bkSolid; // and not Key.Canvas.Fill ...
Key.Stroke.Thickness := 1;
Key.Stroke.Color := TAlphaColors.Darkgray;
Key.Paint;

Why the TRectangle paints on the canvas of its Parent.Parent (in this case) when drawing on its Canvas beats me. Maybe it has no Canvas itself and TRectangle.Canvas is just a reference to its Parent.Canvas?

Arnold
  • 4,578
  • 6
  • 52
  • 91
  • 2
    I have the same need as you and having the same problems, however I have tried your solution and PAINT is now protected on XE5, I am still getting my run time created rectangle with no color (remains transparent) everything else works. Have you tried that on XE5? any idea can share? thanks – Eduardo Elias May 22 '14 at 12:24
  • for future readers, Firemonkey is not like VCL only the parant form has a handle to interact with the os all child controls will be drawn on the same window, so they share the same canvas of that window, in later versions of delphi this problem is gone and both ways of drawing are working without problems. – Nasreddine Galfout Oct 14 '20 at 09:19
  • https://www.howtobuildsoftware.com/index.php/how-do/huH/delphi-firemonkey-need-help-to-find-firemonkey-equivalent-of-the-vcl-tpaintboxcanvashandle-in-the-context-of-building-graph for reference – Nasreddine Galfout Oct 14 '20 at 09:19