Board index » delphi » Scrolling in DBGrid

Scrolling in DBGrid


2003-08-25 01:18:52 AM
delphi115
Hi!
How can I scroll the display of a DBGrid, without changing the row
selection? For example, suppose I wanted to place the currently selected
row in the center of the grid. How could I do such a thing?
Thanks!
Jonathan Neve.
 
 

Re:Scrolling in DBGrid

Scrolling the grid without selecting is impossible. A scrollbox isn't going
to work either cause the headers will disappear.
If you want to keep the record in the middle use this:
var
Id: Integer;
procedure TForm1.DataSource1DataChange(Sender: TObject; Field: TField);
begin
if Table1.Fields[0].AsInteger <>Id then
begin
Id := Table1.Fields[0].AsInteger;
Table1.Findkey([Id]);
end;
end;
"Jonathan Neve" <jonathan@!nospam!microtec.fr>schreef in bericht
Quote
Hi!

How can I scroll the display of a DBGrid, without changing the row
selection? For example, suppose I wanted to place the currently selected
row in the center of the grid. How could I do such a thing?

Thanks!

Jonathan Neve.

 

Re:Scrolling in DBGrid

Mike Shkolnik writes:
Quote
You may use TopRow property from protected area:

type
THackGrid = class(TDBGrid);

procedure ...
begin
THackGrid(yourDBGrid).TopRow := <calculated row position>
end;
Thanks, but do you know how this would be written in C++ (I use C++Builder)?
Do you mean I need to derive my own DBGrid descendant?
Thanks!
Jonathan Neve.
 

Re:Scrolling in DBGrid

"Jonathan Neve" <jonathan@!nospam!microtec.fr>writes
Quote

Thanks, but do you know how this would be written in C++ (I use
C++Builder)?
Do you mean I need to derive my own DBGrid descendant?
Sinces this is a delphi newsgroup, most people would assume you were talking
about Delphi.
--
Clay Shannon, author of "the Wacky Misadventures of Warble McGorkle"
Download it at tinyurl.com/cent
 

Re:Scrolling in DBGrid

The same in CB will look so:
static_cast<THackGrid*>(yourDBGrid)->.TopRow = <calculated row position>;
"Jonathan Neve" <jonathan@!nospam!microtec.fr>writes
Quote
Mike Shkolnik writes:
>You may use TopRow property from protected area:
>
>type
>THackGrid = class(TDBGrid);
>
>procedure ...
>begin
>THackGrid(yourDBGrid).TopRow := <calculated row position>
>end;

Thanks, but do you know how this would be written in C++ (I use
C++Builder)?
Do you mean I need to derive my own DBGrid descendant?

Thanks!

Jonathan Neve.

 

Re:Scrolling in DBGrid

Mike Shkolnik writes:
Quote
The same in CB will look so:

static_cast<THackGrid*>(yourDBGrid)->.TopRow = <calculated row position>;
Thanks a lot. But what is THackGrid? Do you simply mean that I should
derive a new grid (called THackGrid), and publish the TopRow property?
Thanks!
Jonathan Neve.
 

Re:Scrolling in DBGrid

"Jonathan Neve" <jonathan@!nospam!microtec.fr>writes
Quote
How can I scroll the display of a DBGrid, without changing the row
selection? For example, suppose I wanted to place the currently selected
row in the center of the grid. How could I do such a thing?
If all that is required is to centre the active record in the grid then
GetBookmark followed by GotoBookmark achieves a similar effect
to FindKey without the need to refer to fields.
The use of TopRow may not deliver the behaviour you were looking for but what
follows may not either. You have not described how you intend to implement
the action, or why you were particularly looking for it, but in these examples
I have simply used two buttons to activate the scrolling. If you were
thinking to integrate such behaviour with the standard scrollbars then that
would require yet more tinkering. I have not explored the potential there but
it may not be straightforward. Anyway, this gives you something to play with
and allows you to explore some of the possibilities.
The two examples were written in D2 an BCB4. Check-out the different
behaviour when 'Static' is set false. When set true, the selected row will
hold its display position as far as it can while the grid is scrolled. The
active record though (mostly) appearing static will in reality be scrolling in
the opposite direction to the grid. To get a proper view of the functionality
you should use a result set that has at least twice the number rows as are
visible in the grid.
You don't have to incorporate it into a component but if you intend to re-use
any scheme then it would make sense to do so.
Delphi first...
--------------------------------------
uses
Windows, Messages,... etc.
type
TExposedDBGrid = class(TDBGrid);
type
TForm1 = class(TForm)
...
procedure TForm1.UpBtnClick(Sender: TObject);
begin
ScrollGrid(true, true); // Scroll grid up, static row
end;
procedure TForm1.DownBtnClick(Sender: TObject);
begin
ScrollGrid(false, true); // Scroll grid down, static row
end;
procedure TForm1.ScrollGrid(Up, Static: Boolean);
var
AR, RC, L: Integer;
begin
with TExposedDBGrid (DBGrid1) do
begin
Perform(WM_SETREDRAW, 0, 0);
try
AR := DataLink.ActiveRecord;
RC := RowCount - FixedRows;
if Up then
begin
L := RC - AR;
DataSource.DataSet.MoveBy(L);
if NOT(DataSource.DataSet.EOF) then
begin
if ((NOT(Static)) AND (AR>0)) then
DataSource.DataSet.MoveBy(-(L))
else
DataSource.DataSet.MoveBy(-(L-1));
end
else
DataSource.DataSet.MoveBy(-(L-2));
end
else
begin
DataSource.DataSet.MoveBy(-(AR+1));
if NOT(DataSource.DataSet.BOF) then
begin
if (Static OR (AR = RC-1)) then
DataSource.DataSet.MoveBy(AR)
else
DataSource.DataSet.MoveBy(AR+1);
end
else
DataSource.DataSet.MoveBy(AR-1);
end;
finally
DBGrid1.Perform(WM_SETREDRAW, 1, 0);
DBGrid1.Invalidate;
end;
end;
end;
--------
The BCB version...
Unit1.cpp
//---------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include "DM1.h"
#include "DMMain.h"
//---------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------
class TExposedTable : public TTable
{
public:
__property ActiveRecord;
};
//---------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------
void __fastcall TForm1::ScrollGrid(bool Up, bool Static)
{
DBGrid1->Perform(WM_SETREDRAW, 0, 0);
try
{
int AR = ((TExposedTable *)DBGrid1->DataSource->DataSet)->ActiveRecord;
int RC = ((TStringGrid*)DBGrid1)->RowCount
- ((TStringGrid*)DBGrid1)->FixedRows;
if (Up)
{
int L = RC - AR;
DBGrid1->DataSource->DataSet->MoveBy(L);
if (!(DBGrid1->DataSource->DataSet->Eof))
{
if ((!Static) && (AR>0))
DBGrid1->DataSource->DataSet->MoveBy(-(L));
else
DBGrid1->DataSource->DataSet->MoveBy(-(L-1));
}
else
DBGrid1->DataSource->DataSet->MoveBy(-(L-2));
}
else
{
DBGrid1->DataSource->DataSet->MoveBy(-(AR+1));
if (!(DBGrid1->DataSource->DataSet->Bof))
{
if (Static || (AR == RC-1))
DBGrid1->DataSource->DataSet->MoveBy(AR);
else
DBGrid1->DataSource->DataSet->MoveBy(AR+1);
}
else
DBGrid1->DataSource->DataSet->MoveBy(AR-1);
}
}
__finally
{
DBGrid1->Perform(WM_SETREDRAW, 1, 0);
DBGrid1->Invalidate();
}
}
//---------------------------------------------------------
void __fastcall TForm1::UpBtnClick(TObject *Sender)
{
ScrollGrid(true, false);
}
//---------------------------------------------------------
void __fastcall TForm1::DownBtnClick(TObject *Sender)
{
ScrollGrid(false, false);
}
//---------------------------------------------------------
And if you want to test the TopRow behaviour...
class TExposedDBGrid : public TDBGrid
{
public:
__property TopRow;
};
//---------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
((TExposedDBGrid*)DBGrid1)->TopRow = 6; // or whatever
}
//---------------------------------------------------------
--
Regards,
Chris Luck.
 

Re:Scrolling in DBGrid

"Chris Luck" <XXXX@XXXXX.COM>writes
Minor typo in the Delphi version.
Quote
finally
DBGrid1.Perform(WM_SETREDRAW, 1, 0);
DBGrid1.Invalidate;
end;
Should be -
finally
Perform(WM_SETREDRAW, 1, 0);
Invalidate;
end;
--
Regards,
Chris Luck.
 

Re:Scrolling in DBGrid

Thanks a lot for your reply.
It seems from your code that I can actually take a DBGrid, and cast it
to a type that it doesn't descend from (TExposedDBGrid). This is very
strange, but I will give it a try!
Thanks again!
Jonathan Neve.
 

Re:Scrolling in DBGrid

"Jonathan Neve" <jonathan@!nospam!microtec.fr>writes
Quote
Thanks a lot for your reply.
It seems from your code that I can actually take a DBGrid, and cast it
to a type that it doesn't descend from (TExposedDBGrid). This is very
strange, but I will give it a try!
An on-the-fly decendant type of TDBGrid is created of type TExposedDBGrid .
In the BCB form the required property is raised in visibility to make it
accessible. Your DBGrid is cast as being the new type and gets access to the
newly exposed property. It is described as a 'Hack', but Borland make use of
it in the VCL.
--
Regards,
Chris Luck.