Re: change delphi stringgrid cell colors

Posted by webmaster Guido

In Reply to Re: Making a grid with FG/BG setable colors posted by Lee Hallin

: Thanks Guido,

: Thanks for such a complete list of different ways to do it!

: I'm a long time (30+ yrs) programmer but am relatively new to the "visual" stuff.

: It looks like the TStringGrid would be simplest. I just played with it a little and was confused at what I saw (one block that looked like it had 5 columns and 5 rows) but it was ONE unit on the form. I'll play some more when it's earlier in my day :-) and get back to you!

Here's some code to play with :)

1. Add a Delphi TStringGrid component to the form. In the Object Inspector, set the following properties:

ColCount : default 5 or whatever number you prefer
RowCount : default 5 or whatever number you prefer
FixedCols : 0
FixedRows : 0
Name : Grid

2. In the implementation part of the unit, before the first procedure or function, declare two dynamic arrays that will hold the forground / background colours:

  FG: array of array of TColor;
  BG: array of array of TColor;

3. At the start of the program, we have to initialize the arrays. Code the OnCreate event handler of the form as follows:

procedure TForm1.FormCreate(Sender: TObject);
  Col, Row: integer;
  // Set the sizes of the arrays
  SetLength(FG, Grid.ColCount, Grid.ColCount);
  SetLength(BG, Grid.ColCount, Grid.ColCount);
  // Initialize with default colors
  for Col := 0 to Grid.ColCount - 1 do begin
    for Row := 0 to Grid.RowCount - 1 do begin
      FG[Col, Row] := clBlack;
      BG[Col, Row] := clWhite;

3. Let Delphi write the template of an event handler: on the form, select the stringgrid component, and on the Events page of the Object Inspector, double click on the rectangle next to OnDrawCell.

4. Complete the event handler as follows:

procedure TForm1.GridDrawCell(Sender: TObject; ACol, ARow:
  Rect: TRect; State: TGridDrawState);
  S: string;
  S := Grid.Cells[ACol, ARow];
  // Fill rectangle with colour
  Grid.Canvas.Brush.Color := BG[ACol, ARow];
  // Next, draw the text in the rectangle
  Grid.Canvas.Font.Color := FG[ACol, ARow];
  Grid.Canvas.TextOut(Rect.Left + 2, Rect.Top + 2, S);

5. Let's write a quick routine for testing. When we click on a stringgrid cell, it should show the text "clicked" and set foreground/background colours randomly but with enough contrast.

procedure TForm1.GridClick(Sender: TObject);
  Col, Row: integer;
  Colo1, Colo2, Colo3: byte;
  Col := Grid.Col;
  Row := Grid.Row;
  // Calculate contrasting random colours
  Colo1 := 200 + Random(56);
  Colo2 := 200 + Random(56);
  Colo3 := 100 + Random(156);
  BG[Col, Row] := RGB(Colo1, Colo2, Colo3);
  FG[Col, Row] := RGB(255 - Colo3, 255 - Colo1, 255 - Colo2);
  // Set the text to be displayed
  Grid.Cells[Col, Row] := 'clicked';

Note that you can not directly change the colour of a cell, you can only tell the system that it should use such and such colours when next time it redraws the cell. In our example, it is the statement
Grid.Cells[Col, Row] := 'clicked';
that tells the system to redraw a cell. If that cell it is visible at that moment, the OnDrawCell event of the stringgrid is fired automatically. Finally, the event calls the event handler GridDrawCell.

Note also that if the stringgrid (or part of it) becomes visible again after it was hidden (e.g. obscured by another window), then GridDrawCell is called automatically for every cell that becomes visible.


Related Articles

Annoying StringGrid Focus
... setting the focus on the upper lefthand cell [0,0] and coloring it dark blue. This obfuscates what i want to show in that cell...

StringGrid Column widths
How to set the width of individual columns of a StringGrid? You can't do this at with the Object Inspector...

Auto-size your StringGrid
Automatically adapt the width of a stringgrid column to the contents of its widest cell.

Change cell color if...
How to colour a stringgrid cell in red, if that cell contains a negative value?