Setting background color of selected row on TStringGrid
Asked Answered
Q

4

6

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;
Quintic answered 7/4, 2011 at 3:45 Comment(2)
Mawg, this is off topic, but I suspect clAqua will look weird - it's a very bright colour! Try clHighlight instead since it's a system colour meant to represent the highlighted / selected object.Oberland
Be sure to explicitly set the foreground color if you set the background color. AFAICT you combine clAqua BG with clWindowText FG, and the latter can be changed by the user via the system's graphics settings.Jetty
B
7

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;
Ballance answered 7/4, 2011 at 5:6 Comment(4)
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?Quintic
Uff, @Quintic 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.Ballance
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).Ballance
+ for both. I was unaware of goRowSelect and suspect that that is what I want. I will check it out. Thanks.Quintic
G
2

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

Glick answered 7/4, 2011 at 4:2 Comment(1)
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?Quintic
I
2

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.

Illa answered 7/4, 2011 at 8:45 Comment(0)
H
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)

Handstand answered 10/10, 2014 at 16:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.