title: How To Toggle The cell Colour And Text In A TStringGrid On And Off
body: <p>I am running Lazarus v0.9.30 (32 bit compiler).</p>
  
  <p>I have a TForm with a standard TStringGrid on it.  The grid has the following properties set.  RowCount = 5, ColumnCount = 5, FixedCols = 0, FixedRows = 0.</p>
  
  <p>I Googled some <a href="http://www.festra.com/wwwboard/messages/12892.html" rel="nofollow">code</a> that showed me how to change the cell colour and add some text to the cell when a user clicks on a TStringGrid cell.  All works fine and I have extended it slightly to toggle the color/text on and off on the GridClick event. </p>
  
  <p>The questions I have are more to better understand the purpose behind some of the elements of the code.</p>
  
  <p>There is an array of Foregroud (FG) and Background (BG) TColor objects.  Are they there to store the cell color attributes that are set on the GridClick event, so if the DrawCell event needs to get triggered again for any reason the cell can redraw itself?  Can you avoid using the array of TColors and just set the colour / text in the DrawCell event as required?</p>
  
  <p>If you need to use the arrays, I would assume that dimensions must match the Grid.ColCount and Grid.RowCount (ie. set via the SetLength call in Form.Create)</p>
  
  <p>Is there a way to detect that you are clicking outside of the 5 x 5 cells of the  stringgrid (ie in the whitespace) and thus prevent the GridClick from calling the DrawCell event.  No matter where you click you always get a valid value for Row and Col.</p>
  
  <pre><code>unit testunit;
  
  {$mode objfpc}{$H+}
  
  interface
  
  uses
    Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
    ExtCtrls, Menus, ComCtrls, Buttons, Grids, StdCtrls, Windows, Variants,
    LCLType;
  type
  
    { TForm1 }
  
    TForm1 = class(TForm)
      Grid: TStringGrid;
      procedure FormCreate(Sender: TObject);
      procedure GridClick(Sender: TObject);
      procedure GridDrawCell(Sender: TObject; aCol, aRow: Integer;
        aRect: TRect; aState: TGridDrawState);
    end; 
  
  var
    Form1: TForm1; 
  
  implementation
  
  var
    FG: array of array of TColor;
    BG: array of array of TColor;
  
  {$R *.lfm}
  
  { TForm1 }
  
  procedure TForm1.FormCreate(Sender: TObject);
  var
    Col, Row: integer;
  begin
    // Set the sizes of the arrays
    SetLength(FG, 5, 5);
    SetLength(BG, 5, 5);
  
    // 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;
      end;
    end;
  end;
  
  procedure TForm1.GridDrawCell(Sender: TObject; aCol, aRow: Integer;
    aRect: TRect; aState: TGridDrawState);
  var
    S: string;
  begin
    S := Grid.Cells[ACol, ARow];
  
    // Fill rectangle with colour
    Grid.Canvas.Brush.Color := BG[ACol, ARow];
    Grid.Canvas.FillRect(aRect);
  
    // Next, draw the text in the rectangle
    Grid.Canvas.Font.Color := FG[ACol, ARow];
    Grid.Canvas.TextOut(aRect.Left + 22, aRect.Top + 2, S);
  end;
  
  procedure TForm1.GridClick(Sender: TObject);
  var
    Col, Row: integer;
  begin
    Col := Grid.Col;
    Row := Grid.Row;
  
    // Set the cell color and text to be displayed
    if (Grid.Cells[Col,Row] &lt;&gt; 'Yes') then
      begin
        BG[Col, Row] := rgb(131, 245, 44);
        FG[Col, Row] := RGB(0, 0, 0);
        Grid.Cells[Col, Row] := 'Yes'
      end {if}
    else
      begin
        BG[Col, Row] := rgb(255, 255, 255);
        FG[Col, Row] := RGB(255, 255, 255);
        Grid.Cells[Col, Row] := '';
      end; {else}
  end;
  
  end.
  </code></pre>