Delphi's TDBGrid displays and manipulates records from a dataset in a tabular grid.
Contrary to what most novice developers think, the DBGrid component allows various customizations.
Changing the color of a specific cell or a column or even a row is not complicated at all.
What most are not aware of, is that you can even implement the OnMouseHover (hot tracking) behavior to change the display (color, font, etc.) of the DBGRid's (data) row underneath the mouse - *not* the currently selected row - thus making it look like today's web driven interfaces.
I'm sure you've seen this behavior many times - many tables on the Web change the background color of their rows as mouse hovers over them.
OnMouseHover - how to know where the mouse is?
To add this feature to your Delphi database applications displaying data in a DGBGrid component you need to know a few [/link url=/od/usedbvcl/a/tdbgrid.htm]TDBGrid tricks[/link]!Obviously, you need to know how to enhance the display functionality of a TDBgrid component using colors.
The key event here is the OnDrawColumnCell event - it allows you to provide customized drawing for the data in the cells of the grid.
The implementation we are looking for is to change the color of the row under the mouse pointer.
Also, you need to know over what DBGrid row the mouse is.
Plus, you need to be aware of the protected hack technique, that allows you to access protected members of a class.
Coloring DBGrid's Row On Mouse Hover
To follow the source code provided later on, create a new application. On the form ("Form1") drop a DBGrid ("DBGrid1"). Use any type of TDataset descentand and connect to some database data to make sure the dbgrid has some data to show.Note: All he code goes inside the Form1's unit source!!
For a start, prepare the protected hack for the DBGrid component. In the interface section, just add the following line:
type
THackDBGrid = class(TDBGrid) ;
Next, add a private integer property "MouseOverRow" - you'll use it to track the index position of the row the mouse is over.
privateTo be able to track the row the mouse is over you need to handle the OnMouseMove DBGrid1's event.
fMouseOverRow: integer;
procedure SetMouseOverRow(const Value: integer) ;
property MouseOverRow : integer read fMouseOverRow write SetMouseOverRow;
//DBGrid1 OnMouseMoveThe MouseOverRow property's setter calls the Refresh method that will in turn fire the DrawColumnCell event.
procedure TForm1.DBGrid1MouseMove(
Sender: TObject;
Shift: TShiftState;
X, Y: Integer) ;
var
gc: TGridCoord;
begin
gc := DBGrid1.MouseCoord(x, y) ;
MouseOverRow := gc.Y;
end
procedure TForm1.SetMouseOverRow(const Value: integer) ;As expected the tricky part goes inside the OnDrawColumnCell event handling procedure.
begin
if fMouseOverRow <> Value then
begin
fMouseOverRow := Value;
DBGrid1.Repaint;
end;
end;
//DBGrdi1 OnDrawColumnCell
procedure TForm1.DBGrid1DrawColumnCell(
Sender: TObject;
const Rect: TRect;
DataCol: Integer;
Column: TColumn;
State: TGridDrawState) ;
begin
if NOT ((gdFocused in State) or (gdSelected in State))
AND (MouseOverRow = 1 + THackDBGrid(DBGrid1).DataLink.ActiveRecord) then
begin
with DBGrid1.Canvas do
begin
Brush.Color := clSilver;
Font.Color := clNavy;
end;
end;
DBGrid1.DefaultDrawColumnCell(Rect, DataCol, Column, State) ;
end;
What we want is to change the drawing color of the row the mouse is over.
Therefore:
If MouseOverRow matches the ActiveRecord value of the protected DataLink property and the cell being drawn does not have the focus and is not selected: change the Canvas's coloring to actually "draw" the row highlighted.
The tricky part here was the protected DataLink property and the ActiveRecord value. The DataLink property helps the data-aware grid manage its link to the data source and respond to data events. The ActiveRecord specifies the index of the current record within the internal record buffer maintained by the dataset for the Owner of the TDataLink object.
You might think that ActiveRecord points to the currently selected record for the data displayed in the grid, but it is not.
Note: you might ask yourself: "how does he know this". Here's the answer: I read Delphi Help files and browse the VCL source code.
While Delphi draws data the DBGrid displays it changes the ActiveRecord to match the row being drawn.
And this is the trick: match the currently drawn row woth the one the mouse is over. That's it. Beauty!


