Author: Tomas Rutkauskas
I have a TStringGrid component and I want change the color of the text in one row.
Answer:
Any kind of custom drawing in a TStringgrid requires a OnDrawCell handler (or
overriding the DrawCell method in a derived grid class). Often this is not
enough,however. If you base your special drawing on the active cell or its row or
column you also need to make sure cells you previously drew in your custom manner
are redrawn normal when the active cell moves, that the grid shows the special
drawing only when it has focus and so on. This can get a bit complex, as shown by
the sample below.
Note that is is simpler when you only customize the active cell, since this cell
will be redrawn automatically when it is activated or deactivated.
1 unit Unit1;
2
3 interface
4
5 uses
6 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
7 ComCtrls, StdCtrls, Grids;
8
9 const
10 UM_INVALIDATEROW = WM_USER + 321;
11 type
12 TForm1 = class(TForm)
13 StatusBar: TStatusBar;
14 Button1: TButton;
15 OpenDialog1: TOpenDialog;
16 Label1: TLabel;
17 StringGrid1: TStringGrid;
18 Edit1: TEdit;
19 procedure StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect;
20 State: TGridDrawState);
21 procedure StringGrid1Enter(Sender: TObject);
22 procedure StringGrid1SelectCell(Sender: TObject; ACol, ARow: Integer; var
23 CanSelect: Boolean);
24 procedure StringGrid1Exit(Sender: TObject);
25 private
26 { Private declarations }
27 FGridActive: Boolean;
28 procedure UMInvalidateRow(var msg: TMessage); message UM_INVALIDATEROW;
29 public
30 { Public declarations }
31 end;
32
33 var
34 Form1: TForm1;
35 dummy: Integer;
36
37 implementation
38
39 {$R *.DFM}
40
41 type
42 TGridCracker = class(TStringgrid); { gives access to protected methods }
43
44 procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
45 Rect: TRect; State: TGridDrawState);
46 var
47 grid: TStringgrid;
48 begin
49 {Task: color the current row}
50 grid := Sender as TStringgrid;
51 if FGridActive and (aRow = grid.Row) and (aCol >= grid.FixedCols) then
52 begin
53 grid.Canvas.brush.Color := clBlue;
54 grid.canvas.font.color := clWhite;
55 grid.canvas.FillRect(Rect);
56 InflateRect(rect, -2, -2);
57 grid.Canvas.TextRect(Rect, rect.left, rect.top, grid.cells[aCol, aRow]);
58 end
59 else if (gdSelected in State) and not grid.Focused then
60 begin
61 grid.Canvas.brush.Color := grid.color;
62 grid.canvas.font.color := grid.font.color;
63 grid.canvas.FillRect(Rect);
64 InflateRect(rect, -2, -2);
65 grid.Canvas.TextRect(Rect, rect.left, rect.top, grid.cells[aCol, aRow]);
66 end;
67 end;
68
69 procedure TForm1.StringGrid1Enter(Sender: TObject);
70 begin
71 if Sender is TStringgrid then
72 with TGridCracker(sender) do
73 PostMessage(self.handle, UM_INVALIDATEROW, Row, Integer(sender));
74 FGridActive := true;
75 { Cannot rely on grid.focused here, it is not yet true when the message send
76 above is processed for some reason. }
77 end;
78
79 procedure TForm1.StringGrid1SelectCell(Sender: TObject; ACol, ARow: Integer;
80 var CanSelect: Boolean);
81 var
82 grid: TStringgrid;
83 begin
84 grid := Sender as TStringgrid;
85 if grid.Row <> aRow then
86 PostMessage(handle, UM_INVALIDATEROW, grid.Row, Integer(grid));
87 PostMessage(handle, UM_INVALIDATEROW, aRow, Integer(grid));
88 end;
89
90 procedure TForm1.UMInvalidateRow(var msg: TMessage);
91 begin
92 TGridCracker(msg.lparam).InvalidateRow(msg.wparam);
93 end;
94
95 procedure TForm1.StringGrid1Exit(Sender: TObject);
96 begin
97 if Sender is TStringgrid then
98 with TGridCracker(sender) do
99 PostMessage(self.handle, UM_INVALIDATEROW, Row, Integer(sender));
100 FGridActive := false;
101 end;
102
103 end.
|