1. Home
  2. Computing & Technology
  3. Delphi Programming

Highlighting Delphi's DBGrid Row On Mouse Hover

Hot Tracking for TDBGrid

By Zarko Gajic, About.com

On Mouse Row Hover Highlight for Delphi's DBGrid

On Mouse Row Hover Highlight for Delphi's DBGrid

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.

  private
    fMouseOverRow: integer;
    procedure SetMouseOverRow(const Value: integer) ;
    property MouseOverRow : integer read fMouseOverRow write SetMouseOverRow;
To be able to track the row the mouse is over you need to handle the OnMouseMove DBGrid1's event.
//DBGrid1 OnMouseMove
procedure TForm1.DBGrid1MouseMove(
  Sender: TObject;
  Shift: TShiftState;
  X, Y: Integer) ;
var
  gc: TGridCoord;
begin
  gc := DBGrid1.MouseCoord(x, y) ;

  MouseOverRow := gc.Y;
end
The MouseOverRow property's setter calls the Refresh method that will in turn fire the DrawColumnCell event.
procedure TForm1.SetMouseOverRow(const Value: integer) ;
begin
  if fMouseOverRow <> Value then
  begin
    fMouseOverRow := Value;
    DBGrid1.Repaint;
  end;
end;
As expected the tricky part goes inside the OnDrawColumnCell event handling procedure.
//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!

Explore Delphi Programming

More from About.com

  1. Home
  2. Computing & Technology
  3. Delphi Programming
  4. Using Data (DB) Controls
  5. Highlighting Delphi's DBGrid Row On Mouse Hover (without Changing the Active Row)

©2008 About.com, a part of The New York Times Company.

All rights reserved.