Drawing in Cells of a StringGrid

This demonstration shows the drawing of (1) green circles with areas proportional to the areas of the countries, (2) red horizontal bars with lengths proportional to the populations and (3) blue rectangle outlines to draw attention to the cells containing the capitals.

To reproduce this form-based application, save a new project as StringGridDraw and the unit as uStringGridDraw. Add to the form a TStringGrid from the Additional components tab. Paste the code below to replace the default code in the unit then using the Object Inspector set the DefaultColWidth to 80 and the DefaultRowHeight to 84. Select for the OnDrawCell event StringGrid1DrawCell.

The code follows a screenshot of the output.

Output

Output

Code of uStringGridDraw.pas

unit uStringGridDraw;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, Grids, ExtCtrls;

type
  TCountry = record
    Name, Capital: string;
    Population, Area: integer;
  end;

  TForm1 = class(TForm)
    StringGrid1: TStringGrid;
    procedure FormCreate(Sender: TObject);
    procedure StringGrid1DrawCell(Sender: TObject; aCol, aRow: Integer;
                                  aRect: TRect; aState: TGridDrawState);
  private
    const
      Countries: array[0..3] of TCountry =
                 ((Name: 'Australia'; Capital: 'Canberra'; Population: 24000000; Area: 7692024),
                 (Name: 'Austria'; Capital: 'Vienna'; Population: 8200000; Area: 84000),
                 (Name: 'Belgium'; Capital: 'Brussels'; Population: 11000000; Area: 31000),
                 (Name: 'Botswana'; Capital: 'Gaborone'; Population: 2200000; Area: 580000));

      FieldNames: array[0..3] of string =
                  ('Name', 'Area (sq km)', 'Population', 'Capital');
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

procedure TForm1.FormCreate(Sender: TObject);
var
  RowNum, ColNum: integer;
begin
  for ColNum := 0 to 3 do
    StringGrid1.Cells[ColNum, 0] := FieldNames[ColNum];
  for RowNum := 1 to 4 do
    begin
      StringGrid1.Cells[0, RowNum] := Countries[RowNum - 1].Name;
      StringGrid1.Cells[1, RowNum] := IntToStr(Countries[RowNum - 1].Area);
      StringGrid1.Cells[2, RowNum] := intToStr(Countries[RowNum - 1].Population);
      StringGrid1.Cells[3, RowNum] := Countries[RowNum - 1].Capital;
    end;
end;

procedure TForm1.StringGrid1DrawCell(Sender: TObject; aCol, aRow: Integer;
                                     aRect: TRect; aState: TGridDrawState);
const
  HB = 2;
  VB = 2;
  k = 24 / sqrt(7692024);  // constant to make Australia's circle fit the cell
var
  r: integer; // radius of green circle
begin
  with StringGrid1 do
    begin
      if (aCol = 1) and (aRow > 0) then
        begin
          Canvas.FillRect(aRect);
          r := round(k * sqrt(StrToInt(Cells[aCol, aRow])));
          Canvas.Brush.Color := clGreen;
          Canvas.Pen.Color := clGreen;
          Canvas.Ellipse(aRect.Right - 24 - r, aRect.Top + 24 - r,
                         aRect.Right - 24 + r, aRect.Top + 24 + r);
          Canvas.Brush.Color := clWhite;
          Canvas.TextOut(ARect.Left + HB, ARect.Top + VB + 20, Cells[ACol, ARow]);
        end;
      if (aCol = 2) and (aRow > 0) then
        begin
          Canvas.FillRect(aRect);
          Canvas.Brush.Color := clRed;
          Canvas.FillRect(aRect.Left, ARect.Top +  VB,
                          aRect.Left + (StrToInt(Cells[aCol, aRow]) div 500000),
                          aRect.Top + 20);
          Canvas.Brush.Color := clWhite;
          Canvas.TextOut(ARect.Left + HB, ARect.Top + VB + 20, Cells[ACol, ARow]);
        end;
      if (aCol = 3) and (aRow > 0) then
        begin
          Canvas.FillRect(ARect);
          Canvas.Pen.Color := clBlue;
          Canvas.Rectangle(ARect.Left + 5, ARect.Top + 5, ARect.Right - 5, aRect.Bottom - 5);
          Canvas.TextOut(ARect.Left + HB + 5, ARect.Top + VB + 20, Cells[ACol, ARow]);
        end;
    end;
  end;
end.
    

Going Further

See StringGrids and Bitmaps on the DelphiForFun website for a demonstration of changing a cell's colour or contents on mouseover and of enabling the user to "paint" an image into the cells.

Programming - a skill for life!

How to use a string grid to display and edit data