Highlight an entire row in a TStringGrid (2) (Views: 28)
Problem/Question/Abstract: 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. unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, StdCtrls, Grids; const UM_INVALIDATEROW = WM_USER + 321; type TForm1 = class(TForm) StatusBar: TStatusBar; Button1: TButton; OpenDialog1: TOpenDialog; Label1: TLabel; StringGrid1: TStringGrid; Edit1: TEdit; procedure StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); procedure StringGrid1Enter(Sender: TObject); procedure StringGrid1SelectCell(Sender: TObject; ACol, ARow: Integer; var CanSelect: Boolean); procedure StringGrid1Exit(Sender: TObject); private { Private declarations } FGridActive: Boolean; procedure UMInvalidateRow(var msg: TMessage); message UM_INVALIDATEROW; public { Public declarations } end; var Form1: TForm1; dummy: Integer; implementation {$R *.DFM} type TGridCracker = class(TStringgrid); { gives access to protected methods } procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); var grid: TStringgrid; begin {Task: color the current row} grid := Sender as TStringgrid; if FGridActive and (aRow = grid.Row) and (aCol >= grid.FixedCols) then begin grid.Canvas.brush.Color := clBlue; grid.canvas.font.color := clWhite; grid.canvas.FillRect(Rect); InflateRect(rect, -2, -2); grid.Canvas.TextRect(Rect, rect.left, rect.top, grid.cells[aCol, aRow]); end else if (gdSelected in State) and not grid.Focused then begin grid.Canvas.brush.Color := grid.color; grid.canvas.font.color := grid.font.color; grid.canvas.FillRect(Rect); InflateRect(rect, -2, -2); grid.Canvas.TextRect(Rect, rect.left, rect.top, grid.cells[aCol, aRow]); end; end; procedure TForm1.StringGrid1Enter(Sender: TObject); begin if Sender is TStringgrid then with TGridCracker(sender) do PostMessage(self.handle, UM_INVALIDATEROW, Row, Integer(sender)); FGridActive := true; { Cannot rely on grid.focused here, it is not yet true when the message send above is processed for some reason. } end; procedure TForm1.StringGrid1SelectCell(Sender: TObject; ACol, ARow: Integer; var CanSelect: Boolean); var grid: TStringgrid; begin grid := Sender as TStringgrid; if grid.Row <> aRow then PostMessage(handle, UM_INVALIDATEROW, grid.Row, Integer(grid)); PostMessage(handle, UM_INVALIDATEROW, aRow, Integer(grid)); end; procedure TForm1.UMInvalidateRow(var msg: TMessage); begin TGridCracker(msg.lparam).InvalidateRow(msg.wparam); end; procedure TForm1.StringGrid1Exit(Sender: TObject); begin if Sender is TStringgrid then with TGridCracker(sender) do PostMessage(self.handle, UM_INVALIDATEROW, Row, Integer(sender)); FGridActive := false; end; end. |