How do I get screen coordinates of the DBGrid cell

Alexander Malakhov picture Alexander Malakhov · Feb 20, 2012 · Viewed 8.2k times · Source

I want to show popup button or fancy message (with coloured background, etc) just under right-bottom corner of particular cell of the current row.

For now I only figured how to get grid coordinates:
x = DBGrid.DataSource.DataSet.RecNo
y = DBGrid.Columns[index]

There is also TCustomGrid.CellRect, which would do what I want, but it's protected and I don't want to inherit and create another component class.

One crazy workaround I can think of is to save TRect-s in onDrawColumnCell event to some array.

So, what do you think ?

EDIT
How do I get screen coordinates of, say, second cell in the current row ?

Answer

Ken White picture Ken White · Feb 20, 2012

You can get the current cell coordinates, using a little deception. :)

Descendants of a component are allowed to access the protected fields of the ancestor class. Since we don't need to do anything except gain access to the protected CellRect method of TDBGrid, we'll create an interposer (do-nothing descendant) that simply allows us access to that protected method. We can then typecast the TDBGrid to that new descendant class and use it to reach the protected method. I name the descendant using THack as a prefix to make it clear that the only purpose of the descendant is to gain access ("hack") the ancestor class.

// implementation
type
  THackDBGrid=class(TDBGrid);

// Where you need the coordinates
var
  CurrRow: Integer;
  Rect: TRect;
begin
  CurrRow := THackDBGrid(DBGrid1).Row;
  Rect := THackDBGrid(DBGrid1).CellRect(ColIndexYouWant, CurrRow);
  // Rect now contains the screen coordinates you need, or an empty
  // rectangle if there is no cell at the col and row specified.
end;

As the OP has indicated in a comment, there's a more detailed description of how this works at delphi.about.com.