Jan Windemuth
Jan Windemuth

Reputation: 486

Getting a Value from a previous Row in DrawColumnCell

I have a dbGrid filled by a MyDAC-SQL-Query set to RowSelect. One column contains a location string and there can be multiple rows for each location.

What i want to do is to give a visual feedback to better distinguish between different locations. So the rows with the first location should have a white background and the second a grey one, the third a white, and so on...

example

I know how to give every second row a different background, but i'm struggeling to detect on which row the location changes.

So, in the DrawColumnCell procedure i would like to look at the location value of the previous row to detect the change. How can i achieve that?

Upvotes: 2

Views: 2017

Answers (1)

Ken White
Ken White

Reputation: 125708

You have to implement some logic to store the previous field's value, and to determine whether or not a new color is necessary.

Here's a quick example of doing so. To set it up, just a few steps are needed - I've started with a new, blank VCL forms application for simplicity.

  • Drop a TClientDataSet on the form, and change it's name to CDS.
  • Add a TDataSource, and set its DataSet to CDS.
  • Next, add a TDBGrid and set its DataSource to DataSource1
  • Change the DBGrid.DefaultDrawing to False.
  • Add three new variables to the form's private section:

    private
      SameCity, SameColor: Boolean;
      LastCity: string;
    
  • Add the following code to the form's OnCreate event to set up the data and initialize the variables:

    procedure TForm1.FormCreate(Sender: TObject);
    var
      i: Integer;
    begin
      // One field dataset, with the exact same cities and rows
      // you've shown in your question
      CDS.FieldDefs.Add('City', ftString, 10);
      CDS.CreateDataSet;
      for I := 1 to 3 do
        CDS.AppendRecord(['London']);
      for i := 1 to 2 do
        CDS.AppendRecord(['Paris']);
      CDS.AppendRecord(['Berlin']);
      for i := 1 to 2 do
        CDS.AppendRecord(['New York']);
      CDS.Open;
    
      // Initialize variables for first use
      LastCity := '';
      SameColor := False;
      SameCity := False;
    end;
    
  • Add an event handler to the DBGrid for the OnDrawDataCell event, with the following code:

    procedure TForm1.DBGrid1DrawDataCell(Sender: TObject; const Rect: TRect;
    Field: TField; State: TGridDrawState);
    const
      RowColors: array[Boolean] of TColor = (clWindow, clLtGray);
    begin
      // See if we're on the same city as the last row, and save the
      // value in the current row for use next row.
      SameCity := (Field.AsString = LastCity);
      LastCity := Field.AsString;
    
      // If they weren't the same, toggle the color value
      if not SameCity then
        SameColor := not SameColor;
    
      // Set the row color and tell the grid to draw the row
      (Sender as TDBGrid).Canvas.Brush.Color := RowColors[SameColor];
      (Sender as TDBGrid).DefaultDrawDataCell(Rect, Field, State);
    end;
    

I've used OnDrawDataCell instead of OnDrawColumnCell because it doesn't get called on the header row or fixed column, so the DBGrid will take care of drawing those completely.

Running the application produces these results.

Grid drawn with colored sets of rows

Upvotes: 2

Related Questions