Setting background color of selected row on TStringGrid

30,265

Solution 1

if you are trying of paint the selected row or cell with a different color you must check for the gdSelected value in the state var.

procedure TForm1.DatabaseNamesStringGridDrawCell(Sender: TObject;
                                                 ACol, ARow: Integer;
                                                 Rect: TRect;
                                                 State: TGridDrawState);
var
  AGrid : TStringGrid;
begin
   AGrid:=TStringGrid(Sender);

   if gdFixed in State then //if is fixed use the clBtnFace color
      AGrid.Canvas.Brush.Color := clBtnFace
   else
   if gdSelected in State then //if is selected use the clAqua color
      AGrid.Canvas.Brush.Color := clAqua
   else
      AGrid.Canvas.Brush.Color := clWindow;

   AGrid.Canvas.FillRect(Rect);
   AGrid.Canvas.TextOut(Rect.Left + 2, Rect.Top + 2, AGrid.Cells[ACol, ARow]);
end;

Solution 2

This works for me

procedure TFmain.yourStringGrid(Sender: TObject; ACol, ARow: Integer; Rect: TRect;
  State: TGridDrawState);
var
  md: integer;
begin
  with yourStringGrid do 
    begin
           if yourStringGrid,Row = ARow then
              Canvas.Brush.Color:= clYellow  //your highlighted color
           else begin
                 md := Arow mod 2;
                 if md <> 0 then Canvas.Brush.Color:= $00BADCC1 else //your alternate color
                 Canvas.Brush.Color:= clwhite;
           end;
           Canvas.FillRect(Rect);
           Canvas.TextOut(L, Rect.top + 4, cells[ACol, ARow]);
        end;
end;

Refresh the grid

procedure TFmain.yourStringGridClick(Sender: TObject);
begin
  yourStringGrid.Refresh;
end;

Note: Has a little latency, but otherwise works great.
(Used in Delphi XE2)

Solution 3

When a new cell is selected in a stringgrid only the previous and the new selected cell are invalidated. Thus the remaining cells of the previous and new row are not redrawn, giving the effect you describe.

One workaround would be to call InvalidateRow for both affected rows, but this is a protected method and you have to find a way to reach this method from an OnSelectCell event handler. Depending on your Delphi version there are different ways to accomplish that.

The cleanest way would be to derive from TStringGrid, but in most cases this is not feasible. With a newer Delphi version you can use a class helper to achieve this. Otherwise you have to rely on the usual protected hack.

Solution 4

Do you have run-time themes enabled? Run-time themes override any colour scheme you try to enforce for Windows Vista and up.

Share:
30,265
Mawg says reinstate Monica
Author by

Mawg says reinstate Monica

Donate a cup of food for free: Click to Give @ The Hunger Site SOreadytohelp

Updated on July 09, 2022

Comments

  • Mawg says reinstate Monica
    Mawg says reinstate Monica almost 2 years

    I have a TStringGrid where the selected row (max 1, no multi-select) should always have a different background colo(u)r.

    I set the DefaultDrawing property to false, and provide a method for the OnDrawCell event, shown below - but it is not working. I can't even describe exactly how it is not working; I supect that if I could I would already have solved the problem. Suffice it to say that instead of having complete rows all with the same background colour it is a mish-mash. Muliple rows have some cells of the "Selected" colour and not all cells of the cselected row have the selected colour.

    Note that I compare the cell's row with the strnggrid's row; I can't check the cell state for selected since only cell of the selected row is selected.

    procedure TForm1.DatabaseNamesStringGridDrawCell(Sender: TObject;
                                                     ACol, ARow: Integer;
                                                     Rect: TRect;
                                                     State: TGridDrawState);
    
      var cellText :String;
    begin
       if gdFixed in State then
          DatabaseNamesStringGrid.Canvas.Brush.Color := clBtnFace
       else
       if ARow = DatabaseNamesStringGrid.Row then
          DatabaseNamesStringGrid.Canvas.Brush.Color := clAqua
       else
          DatabaseNamesStringGrid.Canvas.Brush.Color := clWhite;
    
       DatabaseNamesStringGrid.Canvas.FillRect(Rect);
       cellText := DatabaseNamesStringGrid.Cells[ACol, ARow];
       DatabaseNamesStringGrid.Canvas.TextOut(Rect.Left + 2, Rect.Top + 2, cellText);
    end;
    
  • Mawg says reinstate Monica
    Mawg says reinstate Monica about 13 years
    are you sure? I have great respect for you and for the help which you have given me in the past - but - surely if I click on one cell in a row then only that cell is selected? Not the entire row? Even if it were (which I doubt) what is worng with my code? Isn't it just two ways of specifying thesame thing? Why doesn't it work?
  • Mawg says reinstate Monica
    Mawg says reinstate Monica about 13 years
    XP, but anyway, surely that wouldn't explain the "splodgy" way that cells are selected? If you are right, wouldn't each cell in any given row look the same?
  • RRUZ
    RRUZ about 13 years
    Uff, @Mawg i don't understand what do you mean, in my provided answer the selected row or cell (depending if you are setting the goRowSelect in the Options property) is draw with the color which your choose in this case clAqua if you wanna make another thing you must rephrase your question to help you.
  • RRUZ
    RRUZ about 13 years
    If is difficult to you explain which need to accomplish, you can attach a sample image in your question, of the desired behavior which you want implement (A picture is worth a thousand words).
  • Mawg says reinstate Monica
    Mawg says reinstate Monica about 13 years
    + for both. I was unaware of goRowSelect and suspect that that is what I want. I will check it out. Thanks.