Link to home
Start Free TrialLog in
Avatar of delphimate
delphimateFlag for Australia

asked on

StringGrid Cell Color Change

Hi,

I cannot work out how to change the color of a cell in a stringgrid.

I want the program to place values from a string into a cell and
if the value is say 10 then the cell will change to clRed.

I have read numerious postings on the internet that use
StringGrid1DrawCell

But I cannot get them to work.
If I use this  StringGrid1.color I know this changes the whole grid.

Can anyone HELP !!

Thanks
Bruce
Avatar of PerryDK
PerryDK

I'm completly new to this and this is my first post.  I assume your using Delphi just from your user name.  I wrote your solution in C++ Builder but you should be able to very easily convert it to Delphi.  For the most part just change the -> to .  If you need more help converting it Delphi I'll convert it for you.

Anyway to create this example drop a string grid on your form.  Create a method to initilize the string grid.  And create a OnDrawCell event code handler for your String grid.  This example simply puts 10 random numbers in column 2 and then sets the background color to red if the number is <= 5.

Again let me know if you need help converting to delphi.  Maybe sombody can tell me how to tell from a post what language they are using java, c++, c#, Delphi, etc.

__fastcall TForm1::TForm1(TComponent* Owner)
  : TForm(Owner)
{
  InitializeStringGrid();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::InitializeStringGrid()
{
  StringGrid1->FixedCols = 2;
  StringGrid1->ColCount = 2;
  StringGrid1->Cells[0][0] = "ID";
  StringGrid1->Cells[1][0] = "Random Num";

  //fill the string grid with 10 random numbers
  //the random numbers will be stored in the second column
  StringGrid1->RowCount = 11;
  for(int i = 0; i < 10; i ++)
  {
    StringGrid1->Cells[0][i+1] = i;
    StringGrid1->Cells[1][i+1] = rand() % 10;
  }
}

void __fastcall TForm1::StringGrid1DrawCell(TObject *Sender, int ACol,
      int ARow, TRect &Rect, TGridDrawState State)
{
  //were only intersted in making the cell red if the number is less than
  //or equal to 5.  Since the id's are stored in col one they are of no interest
  if(ACol != 1)
    return;

  //not interested in first row
  if(ARow == 0)
    return;

  int value = StrToInt(StringGrid1->Cells[ACol][ARow]);
  if(value <= 5)
  {
    //make the cell red
    StringGrid1->Canvas->Brush->Color = clRed;
    StringGrid1->Canvas->FillRect(Rect);

    //since we just drew over the entire cell we need to redraw our string on top of the red
    StringGrid1->Canvas->Pen->Color = clBlack;
    StringGrid1->Canvas->TextOut(Rect.Left + 2, Rect.Top + 2, StringGrid1->Cells[ACol][ARow]);
  }

}
Avatar of delphimate

ASKER

Perry,


I am using Delphi 7 and would appreciate if you or somebody could convert your code.

Another questions I have seen this procedure before and don't understand the
line.
StringGrid1->Canvas->TextOut(Rect.Left + 2, Rect.Top + 2, StringGrid1->Cells[ACol][ARow]);

Rec.Left+2  ?


Thanks
Bruce
Description of TextOut taken from help
//------------------------------------------------------
Writes a string on the canvas, starting at the point (X,Y), and then updates the PenPos to the end of the string.

procedure TextOut(X, Y: Integer; const Text: string);

Description

Use TextOut to write a string onto the canvas. The string will be written using the current value of Font. Use the TextExtent method to determine the space occupied by the text in the image. To write only the text that fits within a clipping rectangle, use TextRect instead
//------------------------------------------------------

procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);

Rect is a TRect look up TRect to see what variables are accessable from it in the help file.
Basically it gives you the the top, left, width, and heght of the current cell that you are drawing in coordiantes specific to your TStringGrid

The reason we have to use TextOut is that when we are drawing a cell we first fill it with a red color...this completly hides the default drawing that has occurred so we need to redraw our number "string" back on top of the red stuff in the cell.  The default uses the top and left coordinates and adds 2 to each to give a little bit of an offset so your string isn't directly at the upper left of each cell.  Its just done for appearnce reasons you can change whatever you like including changing the font to yellow for numbers below 3 if you want.

been an awful long time since I programmed in delphi and couldent figure out how to create a function/procedure that takes no arguements so I declared the init as this.

 procedure InitStringGrid(StringGrid1: TStringGrid);


At any rate code listing in Delphi is submittted  below if you have more questions just ask.


//Code Listing

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    StringGrid1: TStringGrid;
    procedure FormCreate(Sender: TObject);
    procedure InitStringGrid(StringGrid1: TStringGrid);
    procedure StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
      Rect: TRect; State: TGridDrawState);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
  InitStringGrid(StringGrid1);
end;

procedure TForm1.InitStringGrid(StringGrid1: TStringGrid);
var
  i: Integer;
begin
  StringGrid1.FixedCols := 2;
  StringGrid1.ColCount := 2;
  StringGrid1.Cells[0, 0] := 'ID';
  StringGrid1.Cells[1, 0] := 'Random Num';

  //fill the string grid with 10 random numbers
  //the random numbers will be stored in the second column
  StringGrid1.RowCount := 11;
  for i := 0 to 9 do
  begin
    StringGrid1.Cells[0, i+1] := IntToStr(i);
    StringGrid1.Cells[1, i+1] := IntToStr(Random(10));
  end;
end;

procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
var
   value : Integer;
begin
  //were only intersted in making the cell red if the number is less than
  //or equal to 5.  Since the id's are stored in col one they are of no interest
  if ACol <> 1 then
    exit;

  //not interested in first row
  if ARow = 0 then
    exit;

  value := StrToInt(StringGrid1.Cells[ACol, ARow]);
  if value <= 5 then
  begin
    StringGrid1.Canvas.Brush.Color := clRed;
    StringGrid1.Canvas.FillRect(Rect);
    StringGrid1.Canvas.Pen.Color := clBlack;
    StringGrid1.Canvas.TextOut(Rect.Left + 2, Rect.Top + 2, StringGrid1.Cells[ACol, ARow]);
  end;
end;

end.
ASKER CERTIFIED SOLUTION
Avatar of PerryDK
PerryDK

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Perry,

Thanks for all your help !!

I have sorted it out.


Bruce.