The conventional solution to this problem is to create a calculated field, and in the OnCalcFields event, set the column value to the RecNo.
This would work for most people, however in my application, it was very buggy because I rapidly resort the table and apply indexes etc.
So I used this workaround:
Create a dummy field in the TDBGrid, call it 'RowNo'.
Then in the DBGrid OnDrawColumnCell event:
If Column.Fieldname = 'RowNo' then
begin
DBGridNumbers.Canvas.textout(Rect.left, rect.top, inttostr(QryTblNumbers.Recno));
end;
For me, this produced the desired results.