Jump to content
Tom F

How to have Live vertical scrolling of TDBGrid

Recommended Posts

I'm sure this has been discussed ad nauseum before, but I haven't been able to find with Google any info on this.  

I'm using VCL in Sydney with FireDac to SQLite.

Is there a way to have a TDBGrid be updated live as I'm dragging the vertical scroll bar, rather than waiting until I release the mouse?

I thought maybe  Qry.FetchOptions.Mode := fmAll; would help. But it doesn't. I had hoped to find some useful info here, but didnt':  https://docwiki.embarcadero.com/RADStudio/Sydney/en/Browsing_Tables_(FireDAC). Nor here: https://docwiki.embarcadero.com/Libraries/Sydney/en/FireDAC.Stan.Option.TFDFetchOptions.CursorKind

I could use a TStringGrid or other component here too, but StringGrids seem to have the same non-live update while vertical scrolling.  I don't want to use a third-party component.

Any suggestions?

TIA

Share this post


Link to post

Thus assuring that anyone who wants to create a modern UI has to rely on third-party tools.  

That's what I was afraid of.  

 

Share this post


Link to post
Quote

What about filing a feature request?

Good idea. It's hard to imagine it hasn't been asked for for literally decades, so I'm not confident of any action on EMB's part.

But, yes, I'll file a feature request. Thanks for the suggestion.

Share this post


Link to post

That could imply potentially hundreds of queries to the DB while you drag?

Share this post


Link to post

Good point, Lars. Yes, it could imply potentially hundreds of queries.

But, in my case, I have several thousand records so there's no reason they couldn't fit in RAM and be updated if the source table changes. No?

Share this post


Link to post
2 minutes ago, Der schöne Günther said:

You can make a fancy looking TListView and fill it yourself.

Yes.  I had hoped that at least a StringGrid would live update (since it's not attached to a data source.)  But, nope. They have the same problem.

Share this post


Link to post
16 minutes ago, Lars Fosdal said:

That could imply potentially hundreds of queries to the DB while you drag?

Not more than a FetchAll would do. It is similar to repeatedly pressing PgDn.

  • Like 1

Share this post


Link to post

I'm using this code called from various places (e.g. WM_SIZE):

Procedure TDBGrid.UpdateScrollBar;
Var
 dataset: TZAbstractRODataSet;
 si: TScrollInfo;
Begin
 dataset := Self.DataSource.DaaSet;
 If Assigned(dataset) Then
 Begin
   If Not dataset.Active Or (dataset.RecordCount <= Self.RowCount - 1) Then
     ShowScrollBar(Self.Handle, SB_VERT, False)
   Else
     Begin
       ShowScrollBar(Self.Handle, SB_VERT, True);
       If Win32MajorVersion >= 6 Then
         SetWindowPos(Self.Handle, 0, 0, 0, 0, 0, SWP_NOSIZE Or SWP_NOMOVE Or SWP_NOZORDER Or SWP_NOACTIVATE Or SWP_NOOWNERZORDER Or SWP_NOSENDCHANGING Or SWP_FRAMECHANGED);
       si.cbSize := sizeof(si);
       si.nMin := 1;
       si.nMax := dataset.RecordCount;
       si.nPos := dataset.RecNo;
       si.fMask := SIF_POS Or SIF_RANGE;
       SetScrollInfo(Self.Handle, SB_VERT, si, True);
     End;
   End
 Else
   ShowScrollBar(Self.Handle, SB_VERT, False);
End;

This should show the position correctly. To make it actually scroll the dataset, do

Procedure TDBGrid.WMHScroll(Var Msg: TWMVScroll);
Var
 dataset: TZAbstractRODataSet;
 si: TScrollInfo;
Begin
 If (Msg.ScrollCode = SB_THUMBTRACK) Or
    (Msg.ScrollCode = SB_THUMBPOSITION) Then
 Begin
   dataset := Self.DataSource.DataSet;
   If Assigned(dataset) Then
   Begin
     si.cbSize := SizeOf(si);
     si.fMask := SIF_ALL;
     If Not GetScrollInfo(Self.Handle, SB_VERT, si) Then
       RaiseLastOSError;
     dataset.MoveBy(si.nTrackPos - dataset.RecNo);
     Msg.Result := 0;
   End
   Else
     inherited;
 End
 Else
   inherited;
End;

I think these two were necessary. If it doesn't work let me know and I'll check what else I added which changes this behavior.
 

Edit: Misread the question, this still won't scroll while you are dragging. I'll leave the code here anyway - it might be useful for some.

 

Edit-Edit: Extended my code with the suggestion of @Uwe Raabe, now it does update properly while the scrollbar is being dragged. Thank you!

Edited by aehimself

Share this post


Link to post
15 hours ago, Uwe Raabe said:

Not more than a FetchAll would do. It is similar to repeatedly pressing PgDn.

True that, but it depends on the number of rows and if the control keeps the already fetched rows or discard them.

I am used to working with tables where fetch all is not an option.

Beyond a certain number - a search is a better option than a scroll bar.

Share this post


Link to post

The requested functionality can be hacked together with a few lines of code. Place this interposer class in the scope of your form.

type
  TDBGrid = class(Vcl.DBGrids.TDBGrid)
  private
    procedure WMVScroll(var Message: TWMVScroll); message WM_VSCROLL;
  end;

...

procedure TDBGrid.WMVScroll(var Message: TWMVScroll);
begin
  if Message.ScrollCode = SB_THUMBTRACK then
    Message.ScrollCode := SB_THUMBPOSITION;
  inherited;
end;

 

  • Like 2
  • Thanks 1

Share this post


Link to post

@Uwe Raabe  Wow!  Amazing!  That works beautifully!!!!  My grid no longer behaves like it was created in the last century.  THANK YOU SO MUCH.  

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×