6

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 ?

Alexander Malakhov
  • 3,383
  • 2
  • 33
  • 58
  • @downvoter: is question not constructive or too open ended or not a real question ? Could you elaborate, so I could improve it ? – Alexander Malakhov Feb 20 '12 at 03:29
  • I'm not the downvoter, but I'd suspect it's because your question isn't clear. Do you want the currently selected cell, the cell under the mouse, the cell being clicked, or something else? – Ken White Feb 20 '12 at 05:43
  • It's a little better. None of your solutions will work, BTW. `RecNo` doesn't necessarily mean anything; index order can affect row ordering, `Columns[Index]` gives you column but not row, and saving coordinates in `OnDrawColumnCell` won't help, as it has no relationship to the current row in the grid except during the time the cell is being drawn. (I don't have a solution to offer (yet), but I can see the flaws in what you're thinking about doing.) – Ken White Feb 20 '12 at 06:39

1 Answers1

10

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.

Ken White
  • 123,280
  • 14
  • 225
  • 444
  • works! Thanks a lot. Btw, I've seen this solution once or twice while googling, but somehow thought that's not it – Alexander Malakhov Feb 20 '12 at 07:50
  • for those interested why this works, it's called "Protected Hack". The technique exploits the fact that protected members of the class are visible to all methods defined in the same unit as the class. Short example [here on SO](http://stackoverflow.com/a/8234371/264047), more elaborate on [by Zarko Gajic](http://delphi.about.com/od/oopindelphi/l/aa082603a.htm) – Alexander Malakhov Feb 20 '12 at 08:29
  • 2
    If this answers your question, may I ask why you're not accepting it as correct? – Ken White Feb 20 '12 at 08:36
  • actually I've accepted it :), but then decided to wait a little to let others to answer (and upvote your answer, btw), maybe someone will come up with solution without a hack. The truth is virtually no one willing to answer will look at closed question. – Alexander Malakhov Feb 20 '12 at 09:24
  • 5
    actually this is the best solution. you could change `THackDBGrid` to `TDBGridAccess` if it makes you less stressed :) casting `TDrawGrid(DBGrid1).CellRect` will also work, but I like this solution less because `TDrawGrid.CellRect` implementation might change (for now it's `Result := inherited CellRect(ACol, ARow)`). – kobik Feb 20 '12 at 14:53
  • @kobik: `if it makes you less stressed` - I'll consider this )) – Alexander Malakhov Feb 21 '12 at 01:23
  • @KenWhite: typo - "CellRect(ColIndexYouWant, Row)" --> "CellRect(ColIndexYouWant, **CurrRow**)" – Alexander Malakhov Feb 22 '12 at 04:08
  • Good catch. I'll fix it for future reference. Thanks. :) – Ken White Feb 22 '12 at 04:11