We help IT Professionals succeed at work.

Changing the colour of CELLS/TEXT in a stringgrid at Runtime...

rperies
rperies asked
on
I have a StringGrid that is linked to a two dimensional array of records and I am trying to change the colour of the text in a stringgrid in order to correspond to a boolean variable field in the array. If the value is false, then the text should be green, otherwise the text should be red (If the value of the field is true). On startup, the text in the cells within the stringgrid is black. On formactivate, I want them to be green, and then, whenever the array is updated, I want them to turn red (when the value in the boolean field, lets call it BOOKED, becomes true)
If the colour of the CELLS, rather than the TEXT can be changed, then I wouldn't mind that either. In fact, I would prefer it.

Thanks

rperies
Comment
Watch Question

Commented:
HI,
Sorry, but I don't know if I sent an answer.
Sincerely,
Nestorua.

Commented:
Did I sent the answer or not?

Commented:
if you wish to change the font color use nect tip :

procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
begin
  StringGrid1.Canvas.FillRect(Rect);
  if ARow = 1 then  {Use ACol for column or use both for a cell}
  begin
    StringGrid1.Canvas.Font.Color := clBlue;
    StringGrid1.Canvas.Font.Name := 'Tahoma' ;
    StringGrid1.Canvas.Font.Style := StringGrid1.Canvas.Font.Style + [fsBold];
  end;
  DrawText(StringGrid1.Canvas.Handle, PChar(StringGrid1.Cells[ACol, ARow]), -1,
                     Rect, DT_SINGLELINE or DT_VCENTER or DT_LEFT);
end;

Commented:
For cell color use StringGrid1.Canvas.Brush.Color := clBlue;

Commented:
HI,
I don?t know why but my answer
Wasn?t sent.
So I try to answer the question as a comment.
The solution of the problem has the following plan:
1.Create a new component from TStringGrid
(let it call TPSIStringGrid).
2.Declare a new TEvent ? TPSIDrawCell.
3.Declare a field  FOnPSIDrawCell of type
TPSIDrawCell.
4.Declare a property OnPSIDrawCell which reads
FOnPSIDrawCell and writes FOnPSIDrawCell.
5.Declare a procedure PSIDrawCell which checks
if FOnPSIDrawCell<>NIL (Assigned).
6.Override the procedure DrawCell in such way:
first execute PSIDrawCell then inherited.
7.Install the TPSIStringGrid on the Pallette.
That?s all.
Now you can change Font and Brush Colors in
OnPSIDrawCell whatever the condition you want.
Sincerely,
Nestorua.

Author

Commented:
Sorry, I appreciate the effort but unfortunately this answer seems far too complicated.

Author

Commented:
Ginsonic - I found that your code worked initially, but I can't assign it to a different procedure, such as a buttonclick. The stringgrid should continue to change colour after the record is updated. Can it be done independently of DrawCell?

rperies
Commented:
Take a look at this demo :

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Grids, StdCtrls;

type
  TForm1 = class(TForm)
    Grid: TStringGrid;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure GridDrawCell(Sender: TObject; ACol, ARow: Integer;
      Rect: TRect; State: TGridDrawState);
    procedure GridSelectCell(Sender: TObject; ACol, ARow: Integer;
      var CanSelect: Boolean);
    procedure Button1Click(Sender: TObject);
    procedure GridSetEditText(Sender: TObject; ACol, ARow: Integer;
      const Value: String);
  private
    procedure AddColumn(Col: integer);
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.AddColumn(Col: integer);
var
 temp, total: real;
 row: integer;
begin
 total := 0;

 for row := 1 to 4 do
   begin

    try
      temp := StrToFloat(Grid.Cells[Col,row]);
    except
      on EConvertError do temp := 0;
    end;

   total := total + temp;
   end;

 Grid.Cells[Col,6] := FloatToStr(total);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 //col first then row
 with Grid do
   begin
   Cells[1,0] := 'Period 1';
   Cells[2,0] := 'Period 2';
   Cells[3,0] := 'Period 3';
   Cells[4,0] := 'Period 4';
   Cells[0,1] := 'Cars';
   Cells[0,2] := 'Pencils';
   Cells[0,3] := 'Computers';
   Cells[0,3] := 'Software';
   Cells[0,4] := 'Books';
   Cells[0,6] := 'Total';
   Cells[1,6] := '0';
   Cells[2,6] := '0';
   Cells[3,6] := '0';
   Cells[4,6] := '0';
   end;
end;

procedure TForm1.GridDrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
var
 strTemp: string;
 Format: integer;
begin
 strTemp := Grid.Cells[ACol,ARow];

 Grid.Canvas.FillRect(Rect);

 if ACol = 0 then
   Format := DT_SINGLELINE or DT_VCENTER or DT_LEFT
 else if ARow = 0 then
   Format := DT_SINGLELINE or DT_VCENTER or DT_CENTER
 else
   Format := DT_SINGLELINE or DT_VCENTER or DT_RIGHT;

 if (ACol = 0) or (ARow = 0) then
   Grid.Canvas.Font.Style := [fsBold]
 else
   Grid.Canvas.Font.Color := clBlue;

 try
   if StrToFloat(strTemp) < 0 then
     Grid.Canvas.Font.Color := clRed; // if negative change to red

   strTemp := FloatToStrF(StrToFloat(strTemp),ffCurrency,18,2);
 except
   on EConvertError do ;//nothing
 end;

 DrawText(Grid.Canvas.Handle,PChar(strTemp),-1,Rect,Format);
end;

procedure TForm1.GridSelectCell(Sender: TObject; ACol, ARow: Integer;
  var CanSelect: Boolean);
begin
 if (ARow = 5) or (ARow = 6) then
   Grid.Options := Grid.Options - [goEditing]
 else
   Grid.Options := Grid.Options + [goEditing];
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 Close;
end;

procedure TForm1.GridSetEditText(Sender: TObject; ACol, ARow: Integer;
  const Value: String);
begin
 AddColumn(ACol);
end;

end.

Commented:
This sample show how can refresh the cell at update.

Commented:
HI, rperies,
What a step of my answer is too complicated for you.
I think you asked not only to know the answer but to know
how to solve problems of the kind and to teach youself
new things.
Sincerely,
Nestorua.