Drawing Shapes in Delphi

Believe me, drawing shapes in Delphi is so easy. To develop a software like CAD, Paint, CorelDraw Delphi provides large number of classes and members that supports to draw shapes on a form or on a graphic control. In Delphi, we draw shapes on canvas of a form or graphic controls. Canvas is an area of form where we can draw shapes, lines and can fill colors on shapes. In Delphi, every form or graphic controls have Canvas property which provides TCanvas object that can be used to draw shapes. TPen object is used to draw lines and we can set size, color of lines. TBrush object is used to set color and style to fill the shapes. Most frequently used classes for drawing shapes are TCanvas , TBitmap, TGraphics, TPen, TBrush

TCanvas
Use TCanvas as a drawing surface for objects that draw an image of themselves

TBitmap 

Bitmap is a powerful graphics object used to create, manipulate (scale, scroll, rotate, and paint), and store images in memory and as files on a disk. 

TGraphics

TGraphics is the abstract base class type for objects such as icons, bitmaps, and meta files that can store and display visual images. It cannot be instantiated. 

TPen 

used to draw lines or outline shapes on a canvas.

TBrush

represents the color and pattern used to fill solid shapes.

TRect

Class which provides a rectangle area of points (left, top, bottom, right)

TFont

Class to change font name, size , color and style when we draw a text.

Even though form’s have also canvas property it’s not a good practice to draw shapes on Delphi forms because we may put other controls on form and may draw on top of the other controls which will result a undesirable result. Even when we minimize and maximize a form you see the drawing image will cleared automatically because after minimize when we maximize the form it tries to repaint the form area to already drawn images will be cleared.


So here in my blog I have used TImage control and its Canvas property to draw shapes. I will also explain how to save the drawing to a bitmap file, how to clear the Canvas and how to re-display the previously saved image.


Every drawing is calculated by position point like a pixel point mostly on basis of x axis and y axis.




So now let's have a look at TImage component example that will draw shapes on Canvas. 


I have put a TImage component on form and set following properties.


object imgDrawArea: TImage

  Left = 0
  Top = 0
  Align = alClient
end

and also put a Button control which on click I will draw shapes on imgDrawArea Canvas.


object btnDraw: TButton

  Left = 192
  Top = 144
  Width = 75
  Height = 33
  Caption = 'Draw'
  TabOrder = 0
  OnClick = btnDrawClick
end

and I have written codes on button click. Here I am drawing a line from point (50,50) to (150,150)


procedure TForm1.btnDrawClick(Sender: TObject);

begin
  with imgDrawArea do
  begin
    Canvas.MoveTo(50,50);
    Canvas.LineTo(150, 150);
  End;
end;

Lets draw lines and different shapes in Delphi using Canvas, Pen and Brush.


Draw a Line.

To draw a line first we need to set initial point that we can set by using Canvas.Moveto procedure and then we need to call Canvas.LineTo method to draw a line.

  with imgDrawArea do

    Canvas.MoveTo(50,50);

After set initial point draw a lint to destination point that we can set by using Canvas.LineTo procedure.


  with imgDrawArea do

    Canvas.LineTo(150, 150);

So here in above example it will draw a line from point (50,50) to (150,150)




Changing Color, Size, Style of line by using TPen object


Delphi provides TPen class to manage lines. Canvas property as Pen property which can be used to change size, color and style of line. Please make sure that we should set all pen related property before drawing shapes.


with imgDrawArea do

begin
  Canvas.Pen.Color := clRed;
  Canvas.Pen.Width := 3;
  Canvas.MoveTo(50,50);
  Canvas.LineTo(150, 150);
End;


Changing line style


Please note that dash or dot style will only effect when Pen width is 1.


with imgDrawArea do

begin
  Canvas.Pen.Width := 1;
  Canvas.Pen.Color := clBlue;
  Canvas.Pen.Style := psDash;
  Canvas.MoveTo(70,70);
  Canvas.LineTo(170, 170);

  Canvas.Pen.Color := clRed;

  Canvas.Pen.Style := psDashDot;
  Canvas.MoveTo(170,70);
  Canvas.LineTo(70, 170);
End;



Draw rectangle

with imgDrawArea do
  Canvas.Rectangle(70, 70, 200, 200);




Change Line color and size. 

with imgDrawArea do
begin
  Canvas.Pen.Color := clRed;
  Canvas.Pen.Width := 2;
End;


Fill color and style.

To fill color and style in rectangle or any covered area we can use TBrush object and its members.

Color

with imgDrawArea do
  Canvas.Brush.Color := clBlue;


No color

with imgDrawArea do
  Canvas.Brush.Style := bsClear;

Style

with imgDrawArea do
   Canvas.Brush.Style := bsVertical;


with imgDrawArea do
  Canvas.Brush.Style := bsFDiagonal;


with imgDrawArea do
   Canvas.Brush.Style := bsCross;


Draw a round rectangle

with imgDrawArea do
  Canvas.RoundRect(60, 60, 200, 200, 10, 10);


Fille with color and style

with imgDrawArea do
begin
  Canvas.Pen.Color := clRed;
  Canvas.Brush.Color := clGreen;
  Canvas.Brush.Style := bsDiagCross;
  Canvas.RoundRect(60, 60, 200, 200, 10, 10);
End;


Draw Focus Rect

var
  R: TRect;
begin
  with imgDrawArea do
  begin
    R := Rect(100, 100, 200, 200);
    Canvas.DrawFocusRect(R);
  end;


Draw circle

with imgDrawArea do
begin
  Canvas.Pen.Width := 2;
  Canvas.Pen.Color := clRed;
  Canvas.Brush.Color := clGreen;
  Canvas.Ellipse(50, 50, 200, 200);
End;



Draw Polygon

  with imgDrawArea do
  begin
    Canvas.Pen.Color := clBlue;
    Canvas.Brush.Color := clTeal;
    Canvas.Polygon([Point(70, 70), Point(250, 250), Point(320, 70),
                         Point(240, 120)]);
  end;



Draw Polyline

  with imgDrawArea do
  begin
    Canvas.Pen.Color := clRed;
    Canvas.Polyline([Point(140, 110), Point(90, 190), Point(200, 140),
                  Point(80, 140), Point(190, 190), Point(140, 110)])
  end;



Draw Arc

  with imgDrawArea do
  begin
      Canvas.Pen.Color := clRed;
      Canvas.Arc(70, 70, 150, 150, 150, 150, 70, 70 );
  end;



Draw Chord

  with imgDrawArea do
  begin
    Canvas.Pen.Color := clBlue;
    Canvas.Chord(100, 100, 300, 300, 300, 100, 100, 100);
  end;


Draw a Pie 

  with imgDrawArea do
  begin
    Canvas.Pen.Color := clWhite;
    Canvas.Brush.Style := bsSolid;
    Canvas.Brush.Color := clLime;
    Canvas.Pie (MulDiv(Width,  15, 100),
                MulDiv(Height, 55, 100),
                MulDiv(Width,  45, 100),
                MulDiv(Height, 85, 100),

                MulDiv(Width,  45, 100),
                MulDiv(Height, 55, 100),
                MulDiv(Width,  15, 100),
                MulDiv(Height, 55, 100));

    Canvas.Brush.Color := clCream;
    Canvas.Pie (MulDiv(Width,  15, 100),
                MulDiv(Height, 55, 100),
                MulDiv(Width,  45, 100),
                MulDiv(Height, 85, 100),

                MulDiv(Width,  15, 100),
                MulDiv(Height, 55, 100),
                MulDiv(Width,  15, 100),
                MulDiv(Height, 85, 100));

    Canvas.Brush.Color := clAqua;
    Canvas.Pie (MulDiv(Width,  15, 100),
                MulDiv(Height, 55, 100),
                MulDiv(Width,  45, 100),
                MulDiv(Height, 85, 100),

                MulDiv(Width,  45, 100),
                MulDiv(Height, 85, 100),
                MulDiv(Width,  45, 100),
                MulDiv(Height, 55, 100));

    Canvas.Brush.Color := clMoneyGreen;
    Canvas.Pie (MulDiv(Width,  15, 100),
                MulDiv(Height, 55, 100),
                MulDiv(Width,  45, 100),
                MulDiv(Height, 85, 100),

                MulDiv(Width,  15, 100),
                MulDiv(Height, 85, 100),
                MulDiv(Width,  45, 100),
                MulDiv(Height, 85, 100));
  end;


Fill a area with FloodFill

procedure TForm1.btnDrawClick(Sender: TObject);
var
  ewidth, eheight: integer;
begin
  with imgDrawArea do
  begin
    ewidth := 300;
    eheight := 200;
    Canvas.Brush.Color := clRed;
    Canvas.Pen.Color := clBlack;
    Canvas.Ellipse(
      (ClientWidth - ewidth) div 2,
      (ClientHeight - eheight) div 2,
      ewidth, eheight);
  end;
end;

procedure TForm1.btnFloodFillClick(Sender: TObject);
var
  R: TRect;
  sText: string;
begin
  with imgDrawArea do
  begin
    Canvas.Brush.Color := clBlue;
    Canvas.Brush.Style := bsCross;
    Canvas.FloodFill( ClientWidth div 2, ClientHeight div 2, clYellow, fsBorder);
  end;
end;


Draw a Text

We can draw text using TextOut or TextRect function. So lets see. 

TextOut

 with imgDrawArea do
  begin
    Canvas.Font.Name := 'Arial';
    Canvas.Font.Color := clBlue;
    Canvas.Font.Size := 20;
    Canvas.Font.Style := [fsItalic];
    Canvas.TextOut(50, 100, 'Jitendra Gouda');
  end;


TextRect

var
  sText: string;
begin
  with imgDrawArea do
  begin
    Canvas.Font.Name := 'Arial';
    Canvas.Font.Color := clRed;
    Canvas.Font.Size := 10;
    Canvas.Font.Style := [fsBold];
    sText := 'Hello, world!';
    Canvas.TextRect(imgDrawArea.ClientRect,50,100,sText);
  end;



Draw Text with different format like center, wrap, framerect

Example 1
var
  Rect1: TRect;
  sText: string;
begin
  with imgDrawArea do
  begin
    Canvas.Font.Name := 'Arial';
    Canvas.Font.Color := clGreen;
    Canvas.Font.Size := 10;
    Canvas.Font.Style := [fsBold];
    sText := 'Hello, world!. Drawing Text with different format.';

    Rect1 := Rect(50, 100, 300, 200);
    Canvas.TextRect(Rect1, sText, [tfCenter, tfWordBreak]);

    Canvas.Brush.Color := clRed;
    Canvas.FrameRect(Rect1);  
  end;
end;



Example 2
var
  Rect1: TRect;
  sText: string;
begin
  with imgDrawArea do
  begin
    Canvas.Font.Name := 'Arial';
    Canvas.Font.Color := clPurple;
    Canvas.Font.Size := 10;
    Canvas.Font.Style := [fsBold];
    sText := 'Hello, world!.';

    Rect1 := Rect(50, 100, 300, 200);
    Canvas.TextRect(Rect1, sText, [tfSingleLine, tfCenter, tfVerticalCenter]);

    Canvas.Brush.Color := clSkyBlue;
    Canvas.FrameRect(Rect1);
  end;
end;


TextHeight and TextWidth

var
  Rect1: TRect;
  sText: string;
  iTextHeight, iTextwidth: integer;
begin
  with imgDrawArea do
  begin
    Canvas.Font.Name := 'Arial';
    Canvas.Font.Color := clGreen;
    Canvas.Font.Size := 10;
    Canvas.Font.Style := [fsBold];
    sText := 'Hello, world!.';

    iTextHeight := Canvas.TextHeight(sText);
    iTextwidth := Canvas.TextWidth(sText);

    Rect1 := Rect(50, 100, 50+iTextwidth, 100+iTextHeight);
    Canvas.TextRect(Rect1, sText, [tfCenter, tfWordBreak]);

    Canvas.Brush.Color := clRed;
    Canvas.FrameRect(Rect1);
  end;
end;


Draw a Triangle

  With imgDrawArea do
  begin
    Canvas.Pen.Color := clBlue;
    Canvas.Pen.Width := 2;
    Canvas.Brush.Color := clSkyBlue;
    Canvas.Brush.Style := bsSolid;
    Canvas.Polygon([Point(150, 50), Point(50, 250), Point(250, 250)]);
  end;



Draw a Star

var
  i, x, y, xx, yy: Integer;
  p: array[0..9] of TPoint;
  t, r, sv, sw, sx, sy, s: Real;
  Rect: TRect;
  FRegion: HRGN;
Begin
  With imgDrawArea do
  begin
    Rect := ClientRect;
    InflateRect(Rect, -2, -2); //decreases rectangle size by 2//
    sx := (Rect.Right-Rect.Left)*0.48;
    sy := (Rect.Bottom-Rect.Top)*0.5;
    if sx > sy then
      sx := sy
    else
      sy := sx;
    sv := (Rect.Left + Rect.Right) / 2;
    sw := (Rect.Top + Rect.Bottom * 1.2) / 2.2;
    for i := 0 to 10 do
    begin
      if ((i and 1) <> 0) then
        r := 1
      else
        r := 0.384;
      t := i * 2 * (PI/10);
      P[i].x := Trunc(sv+sx*r*sin(t));
      P[i].Y := Trunc(sw+sy*r*cos(t));
    end;
    FRegion := CreatePolygonRgn(P, 10, WINDING);

    Canvas.Pen.Color := clRed;
    Canvas.Pen.Width := 2;
    Canvas.Brush.Color := clYellow;
    Canvas.Brush.Style := bsSolid;

    Canvas.Polygon(P);
  end;
end;


Save drawing to a file

  imgDrawArea.Picture.Bitmap.SaveToFile('c:\jitendra\test1.bmp');

Load drawing from a file

  imgDrawArea.Picture.Bitmap.LoadFromFile('c:\jitendra\test1.bmp');


Comments

  1. Nice examples. The TRect summary should read (Left, Top, Right, Bottom)

    ReplyDelete
  2. Hello There. I found your blog using msn. This is a very well written article. I’ll make sure to bookmark it and return to read more of your useful information. Thanks for the post. I’ll definitely return. mac service berlin

    ReplyDelete
  3. Families Portrait Wir Zeichnen Jede Deiner Idee Du hast nie die Gelegenheit ein Bild mit einem geliebten Menschen zu machen und suchst das perfekte Geschenkt für Deine Familie Dann bist Du bei uns genau richtig Foto zeichnen lassen

    ReplyDelete

Post a Comment

Popular posts from this blog

ShellExecute in Delphi

MS Excel Automation in Delphi