トップへ(mam-mam.net/)

Drawing on the Delphi Canvas|Sample Code for Shapes and Text Rendering with TBitmap and TCanvas (VCL/FMXL)

Japanese

Drawing on the Delphi Canvas|Sample Code for Shapes and Text Rendering with TBitmap and TCanvas (VCL/FMXL)

This article introduces how to draw shapes and text on the Delphi Canvas in both VCL and FMX environments.
It explains essential drawing operations—such as filling areas with TBitmap (FillRect), drawing lines, and rendering text (TextRect / FillText)—with practical sample code.

The article also covers custom drawing in VCL using geometric pens (ExtCreatePen), as well as Canvas operations in FMX when working together with TImage.
Detailed control techniques, including drawing sizes, color settings, and font configuration, are thoroughly explained.

Source Code

For VCL

Click "File" -> "New" -> "Windows VCL Application".


Drag and drop a TImage and a TButton onto the form.


Double‑click Button1 and enter the following source code:
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils,
  System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
  Vcl.ExtCtrls;

type
  TForm1 = class(TForm)
    Image1: TImage;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private }
  public
    { Public }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject); var r:TRect; text:String; begin // --- Initial settings for Image1 --- // Set the width and height of Image1 Image1.Width := 200; Image1.Height := 200; // Set the width and height of the internal TBitmap held by TImage Image1.Picture.Bitmap.Width := 100; Image1.Picture.Bitmap.Height := 100; // Set the pixel format to RGB (24‑bit color) Image1.Picture.Bitmap.PixelFormat := TPixelFormat.pf24bit; // Keep the aspect ratio when displaying the image Image1.Proportional := True; // Scale the image to fit the size of TImage // In other words, display the 100×100 bitmap stretched to 200×200 Image1.Stretch := True;
// --- Fill (Solid Color) --- Image1.Picture.Bitmap.Canvas.Brush.Color := $00ff00; // green Image1.Picture.Bitmap.Canvas.Brush.Style := TBrushStyle.bsSolid; // Fill the area from (0,0) to (100-1,100-1) Image1.Picture.Bitmap.Canvas.FillRect( Rect(0, 0, 100, 100) );
// --- Draw a Line --- // Set pen properties Image1.Picture.Bitmap.Canvas.Pen.Width := 1; Image1.Picture.Bitmap.Canvas.Pen.Style := TPenStyle.psSolid; Image1.Picture.Bitmap.Canvas.Pen.Color := $ff0000; // blue // Draw a line from (0,0) to (100-1,100-1) and move the pen to (100,100) Image1.Picture.Bitmap.Canvas.MoveTo(0,0); Image1.Picture.Bitmap.Canvas.LineTo(100,100);
// --- Draw Text --- // Set font color and brush style Image1.Picture.Bitmap.Canvas.Font.Color := $0000ff; // red Image1.Picture.Bitmap.Canvas.Brush.Style := TBrushStyle.bsSolid; // Set the font size in pixels Image1.Picture.Bitmap.Canvas.Font.Height := 10; // 10 pixels // --- Bold text and font settings --- Image1.Picture.Bitmap.Canvas.Font.Style := [TFontStyle.fsBold]; Image1.Picture.Bitmap.Canvas.Font.Name := 'MS PGothic'; // --- Draw text --- text := 'The text will be wrapped automatically and clipped to the specified rectangle.'; r := Rect(0, 20, 50, 60); // output area Image1.Picture.Bitmap.Canvas.TextRect( r, text, [ TTextFormats.tfLeft, TTextFormats.tfTop, TTextFormats.tfWordBreak ] );
end; end.

Run

Run the application and click Button1.


Color Settings

// When Vcl.Graphics is included in the uses clause
Panel1.Color := clRed;

// Specify a color in hexadecimal (green)
Panel1.Color := $00FF00;


Fill with a Custom Pattern

procedure TForm1.Button2Click(Sender: TObject);
var
  pattern: TBitmap;
begin
  // --- Initial settings for Image1 ---
  // Set the width and height of Image1
  Image1.Width := 200;
  Image1.Height := 200;
  // Set the width and height of the internal TBitmap held by TImage
  Image1.Picture.Bitmap.Width := 100;
  Image1.Picture.Bitmap.Height := 100;
  // Set the pixel format to RGB (24-bit color)
  Image1.Picture.Bitmap.PixelFormat := TPixelFormat.pf24bit;
  // Keep the aspect ratio when displaying the image
  Image1.Proportional := True;
  // Scale the image to fit the size of TImage
  // In other words, display the 100×100 bitmap stretched to 200×200
  Image1.Stretch := True;
  // Create a TBitmap for the pattern
  pattern := TBitmap.Create;
  try
    // The pattern bitmap must be 8×8 or smaller; larger sizes are ignored
    pattern.Width := 8;
    pattern.Height := 8;
    pattern.Canvas.Brush.Color := RGB($FF, $FF, $FF);
    pattern.Canvas.FillRect(Rect(0, 0, 8, 8));
    pattern.Canvas.Brush.Color := RGB($77, $77, $77);
    pattern.Canvas.FillRect(Rect(0, 0, 4, 4));
    pattern.Canvas.FillRect(Rect(4, 4, 8, 8));
    // --- Fill using the specified pattern bitmap ---
    Image1.Picture.Bitmap.Canvas.Brush.Bitmap := pattern;
    // Fill the area from (0,0) to (100-1,100-1)
    Image1.Picture.Bitmap.Canvas.FillRect(
      Rect(0, 0, 100, 100)
    );
    Image1.Picture.Bitmap.Canvas.Brush.Bitmap := nil;
  finally
    pattern.Free;
  end;
end;

Using a Geometric Pen Instead of the Default Cosmetic Pen

procedure TForm1.Button3Click(Sender: TObject);
var
  LogBrush: TLogBrush;
  PenStyle: Cardinal;
  pen: HPEN;
  OldPen: HPEN;
  ArrPoint: Array[0..2] of TPoint;
begin
  // --- Initial settings for Image1 ---
  // Set the width and height of Image1
  Image1.Width := 200;
  Image1.Height := 200;
  // Set the width and height of the internal TBitmap held by TImage
  Image1.Picture.Bitmap.Width := 100;
  Image1.Picture.Bitmap.Height := 100;
  // Set the pixel format to RGB (24-bit color)
  Image1.Picture.Bitmap.PixelFormat := TPixelFormat.pf24bit;
  // Keep the aspect ratio when displaying the image
  Image1.Proportional := True;
  // Scale the image to fit the size of TImage
  // In other words, display the 100×100 bitmap stretched to 200×200
  Image1.Stretch := True;

  // Save the existing cosmetic pen
  OldPen := Image1.Picture.Bitmap.Canvas.Pen.Handle;
  // Create a geometric pen
  LogBrush.lbStyle := BS_SOLID;
  LogBrush.lbColor := RGB($0, $cc, $cc);
  LogBrush.lbHatch := 0;
  PenStyle := PS_GEOMETRIC + PS_DASH + PS_ENDCAP_ROUND + PS_JOIN_ROUND;
  pen := ExtCreatePen(PenStyle, 3, LogBrush, 0, nil);
  // Apply the created geometric pen
  Image1.Picture.Bitmap.Canvas.Pen.Handle := pen;
  // Draw a polygon
  ArrPoint[0].X := 0;
  ArrPoint[0].Y := 0;
  ArrPoint[1].X := 99;
  ArrPoint[1].Y := 30;
  ArrPoint[2].X := 40;
  ArrPoint[2].Y := 96;
  Image1.Picture.Bitmap.Canvas.Polygon(ArrPoint);

  // Restore the original cosmetic pen
  Image1.Picture.Bitmap.Canvas.Pen.Handle := OldPen;

  // Delete the created geometric pen
  DeleteObject(pen);
end;

For FMX

Click "File" -> "New" -> "Multi-Device Application".
Select "Blank Application".

Drag and drop a TImage and a TButton onto the form.


Double‑click Button1 and enter the following source code.
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Image1: TImage;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { private }
  public
    { public }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.Button1Click(Sender: TObject); begin // --- Initial settings for Image1 --- // Set the width and height of Image1 Image1.Width := 200; Image1.Height := 200; // Set the width and height of the internal TBitmap held by TImage Image1.Bitmap.Width := 100; Image1.Bitmap.Height := 100; // FMX cannot use BGR (24-bit); it appears to be fixed to BGRA // Not allowed: Image1.Bitmap.PixelFormat := TPixelFormat.BGR; // Keep the aspect ratio when displaying the image // Scale the bitmap to fit the size of TImage // In other words, display the 100×100 bitmap stretched to 200×200 Image1.WrapMode := TImageWrapMode.Fit; //Call before drawing Image1.Bitmap.Canvas.BeginScene();
// --- Fill (Solid Color) --- Image1.Bitmap.Canvas.Fill.Color := $ff00ff00; // green Image1.Bitmap.Canvas.Fill.Kind := TBrushKind.Solid; // Fill the area from (0,0) to (99,99) Image1.Bitmap.Canvas.FillRect( RectF(0, 0, 99, 99), 0, 0, [], 1 );
// --- Draw a Line --- // Set stroke (pen) properties Image1.Bitmap.Canvas.Stroke.Thickness := 1; Image1.Bitmap.Canvas.Stroke.Dash := TStrokeDash.Solid; Image1.Bitmap.Canvas.Stroke.Color := $ff0000ff; // blue // Draw a line from (0,0) to (99,99) Image1.Bitmap.Canvas.DrawLine(PointF(0,0), PointF(99,99), 1);
// --- Draw Text --- // Set color and style Image1.Bitmap.Canvas.Fill.Color := $ffff0000; // red Image1.Bitmap.Canvas.Fill.Kind := TBrushKind.Solid; // Set font size in pixels {$IFDEF MSWINDOWS} // On Windows, divide by 72 and multiply by 96 Image1.Bitmap.Canvas.Font.Size := Image1.Bitmap.Canvas.Font.Size / Image1.Bitmap.Canvas.TextHeight('M') / 72 * 96 * 10; // 10 pixels {$ELSE} Image1.Bitmap.Canvas.Font.Size := Image1.Bitmap.Canvas.Font.Size / Image1.Bitmap.Canvas.TextHeight('M') * 10; // 10 pixels {$ENDIF} // --- Bold text and font settings --- Image1.Bitmap.Canvas.Font.Style := [TFontStyle.fsBold]; // Font family Image1.Bitmap.Canvas.Font.Family := 'MS PGothic'; // Draw text (automatically wrapped and clipped to the rectangle) Image1.Bitmap.Canvas.FillText( RectF(0, 20, 50, 60), 'The text will be wrapped automatically and clipped to the specified rectangle.', true, 1, [], TTextAlign.Leading, TTextAlign.Leading );
//Finish drawing Image1.Bitmap.canvas.EndScene(); end; end.

Run

Run the application and click Button1.


Color Settings

// If System.UITypes is included in the uses clause
Rectangle1.Fill.Color := TAlphaColorRec.Red;

// If System.UITypes is included in the uses clause
Rectangle1.Fill.Color := claBlue;

// Specify a color in hexadecimal (green)
Rectangle1.Fill.Color := $FF00FF00;