...would erase it with the first line of code
(stringgrid1.canvas.fillrect(rect), but this has no effect on the
display
That is because you did not select the Brush.Style
(and possibly also Brush.Color
) just before calling FillRect()
f.ex.
stringgrid1.canvas.Brush.Style := bsSolid; // add this line
stringgrid1.canvas.Brush.Color := clWhite; // add this line
stringgrid1.Canvas.FillRect (Rect);
You will notice that there are some remnants from the default drawing at the left edge of the cells (not visible in the image below, I already fixed them). That is because the TStringGrid
internally offsets the cell drawing with 4 pixels. To change that you need to counter offset the Rect
parameter with -4 and grow the width with +4, also before calling FillRect()
.
After above changes the grid looks very flat and dull (in the image I already added colors to the second grid). To reinstate some color differances for the header column and header row, you need to treat cells with gdFixed in State
with a different Brush.Color
. The same for cells with gdSelected in State
.

The above is what you also need to do if you untick DefaultDrawing
. The second grid and accompanying code demonstrates this. Note that the code also includes a call to DrawFocusRect
when gdFocused in State
just before the end.
Note that I replaced all those Sender as TStringGrid
with a local grid
variable.
procedure TForm4.StringGrid2DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect;
State: TGridDrawState);
var
grid: TStringGrid;
S: String;
drawrect: TRect;
bgFill: TColor;
begin
grid := Sender as TStringGrid;
if gdFixed in State then
bgFill := $FFF8F8
else
if gdSelected in State then
bgFill := $FFF0D0
else
bgFill := clWhite;
grid.Canvas.Brush.Color := bgFill;
grid.canvas.Brush.Style := bsSolid;
grid.canvas.fillrect(Rect);
S := grid.Cells[ACol, ARow];
if Length(S) > 0 then
begin
drawrect := Rect;
drawrect.Inflate(-4 , 0);
DrawText(grid.canvas.handle, Pchar(S), Length(S), drawrect,
dt_calcrect or dt_wordbreak or dt_left);
If (drawrect.bottom - drawrect.top) > grid.RowHeights[ARow] then
grid.RowHeights[ARow] := (drawrect.bottom - drawrect.top+2)
// changing the row height fires the event again!
else
begin
drawrect.Right := Rect.Right;
// grid.canvas.fillrect(drawrect);
DrawText(grid.canvas.handle, Pchar(S), Length(S), drawrect,
dt_wordbreak or dt_left);
end;
end;
if gdFocused in State then
grid.Canvas.DrawFocusRect(Rect);
end;
The third grid demonstrates the easiest and IMO the best solution, wich is to skip the TStringGrid
altogether and use TDrawGrid
instead. You must keep the data you want to show in the grid, separately somewhere. I defined an array: s_arr: array of array of string;
.
In this case you can leave DefaultDrawing
on because the TDrawGrid
doesn't draw any text during the default drawing, the content drawing takes place only in the OnDrawCell
event.
procedure TForm4.DrawGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect;
State: TGridDrawState);
var
S: string;
grid: TDrawGrid;
drawrect: TRect;
begin
grid := Sender as TDrawGrid;
S := s_arr[ACol, ARow];
If Length(S) > 0 Then
Begin
drawrect := Rect;
drawrect.Inflate(-4 , 0);
DrawText(grid.canvas.handle, Pchar(S), Length(S), drawrect,
dt_calcrect or dt_wordbreak or dt_left);
If (drawrect.bottom - drawrect.top) > grid.RowHeights[ARow] Then
grid.RowHeights[ARow] := (drawrect.bottom - drawrect.top + 2)
// changing the row height fires the event again!
Else
Begin
drawrect.Right := Rect.Right;
grid.canvas.fillrect(drawrect);
DrawText(grid.canvas.handle, Pchar(S), Length(S), drawrect, dt_wordbreak or dt_left);
End;
End;
end;
Leaving DefaultDrawing
on, all those theme related features are drawn by the grid itself and we only draw the text on top.