Jump to content
davornik

Adding RecNo/RecCount TPanel to DBGrid

Recommended Posts

I am trying to add TPanel below DBGrid to show information about RecNo/RecCount position in DBGrid.

Something like in attached image.

 

I have tried to do this:

 

type
  TDBGrid = class(Vcl.DBGrids.TDBGrid)
  private
    RecPanel: TPanel;
  protected
    procedure UpdateScrollBar; override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;

...

procedure TDBGrid.UpdateScrollBar;
begin
  //where is proper place to update this?
  RecPanel.Left := Self.Left;
  RecPanel.Width := Self.Width;
  RecPanel.Top := Self.Top + Self.Height;

  //is this best place to be updated?
  if Assigned(Self.DataSource.DataSet) then
    RecPanel.Caption := Self.DataSource.DataSet.RecNo.ToString+'/'+Self.DataSource.DataSet.RecordCount.ToString;

  inherited; // to keep the expected behavior
end;

constructor TDBGrid.Create(AOwner: TComponent);
begin
  inherited;
  RecPanel:=TPanel.Create(TDBGrid(AOwner));
  RecPanel.Parent:=TDBGrid(AOwner);
  RecPanel.Alignment:=taLeftJustify;
  RecPanel.Caption := '0/0';
  RecPanel.Height := 16;
end;

destructor TDBGrid.Destroy;
begin
  RecPanel.Free;
  inherited;
end;

Is there better place to update Panel position and record position data then UpdateScrollBar function?

Does creating Panel like TPanel.Create(TDBGrid(AOwner)) has some benefits than perhaps TPanel.Create(nil)?

 

 

DBGrid+RecNo-RecCount_Panel.png

Share this post


Link to post
TPanel.Create(TDBGrid(AOwner));

The owner of the grid is usually the container (form, frame, etc). Typecasting to the wrong type might cause access violations - simply leave it out. It's unnecessary.

13 hours ago, davornik said:

Does creating Panel like TPanel.Create(TDBGrid(AOwner)) has some benefits than perhaps TPanel.Create(nil)?

The main difference is how the object will be freed. When passing nil as the owner the object has to be freed up manually. Otherwise, it's automatically freed when the owner is freed. I'd suggest using Self (the grid) as the owner of the panel so you can leave out .Free in the destructor.

 

P.s.: When I made a similar component I think I ended up putting the count update logic to the DataChange event but I have to doublecheck...

Edited by aehimself

Share this post


Link to post

Ok, then probably the next step is to make it like this without destructor, perhaps like this?

 

type
  TDBGrid = class(Vcl.DBGrids.TDBGrid)
  private
    RecPanel: TPanel;
    procedure SetRecPanelPos;
  protected
    procedure UpdateScrollBar; override;
    procedure Resize; override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

...

procedure TDBGrid.SetRecPanelPos;
begin
  RecPanel.Left := Self.Left;
  RecPanel.Width := Self.Width;
  RecPanel.Top := Self.Top + Self.Height
end;

procedure TDBGrid.Resize;
begin
  inherited;
  SetRecPanelPos;
end;

procedure TDBGrid.UpdateScrollBar;
begin
  //this must be updated here
  if Assigned(Self.DataSource.DataSet) then
    RecPanel.Caption := Self.DataSource.DataSet.RecNo.ToString+'/'+Self.DataSource.DataSet.RecordCount.ToString;
  inherited; // to keep the expected behavior
end;

constructor TDBGrid.Create(AOwner: TComponent);
begin
  inherited;
  RecPanel:=TPanel.Create(Self);
  RecPanel.Parent:=TDBGrid(AOwner);
  RecPanel.Alignment:=taLeftJustify;
  RecPanel.Caption := '0/0';
  RecPanel.Height := 16;
end;

As far of DataChange event, then I get a message like this: Method 'DataChange' not found in base class...

When doing it like this in designtime I don't have Panel shown below the DBGrid. I always have to reduce height of DBGrid for height of Panel.

I suppose the next step is to create it like a component and install it in Delphi? Then Panel would be shown in designtime?

Share this post


Link to post

So, you have an underlying dataset where RecordCount is always accurate when there are more records then in view? Because often TDataset.RecordCount isn't the actual count of records in the final result. 

 

In that case you would need to show something like: 1/4+ or 1/>4

 

(Or do a TDataset.Last + TDataset.First after opening to get the correct RecordCount)

Share this post


Link to post

DataEvent is a method of the link, not the grid itself:

Type
  TMyGridDataLink = Class(TGridDataLink)
  protected
    Procedure DataEvent(Event: TDataEvent; Info: NativeInt); Override;
  End;

  TDBGrid = Class(Vcl.DBGrids.TDBGrid)
  protected
    Function CreateDataLink: TGridDataLink; Override;
  End;

implementation

Procedure TMyGridDataLink.DataEvent(Event: TDataEvent; Info: NativeInt);
Begin
  inherited;

  // Call your public method of (Self.Grid As TDBGrid) to update it's captions
  // Use Event and Info to make conditions if necessary
End;

Function TDBGrid.CreateDataLink: TGridDataLink;
Begin
  Result := TMyGridDataLink.Create(Self);
End;

As for alignment I used a different approach:

  _ownerpanel := TPanel.Create(Self.Parent);
  _ownerpanel.Top := Self.Top;
  _ownerpanel.Left := Self.Left;
  _ownerpanel.Height := Self.Height;
  _ownerpanel.Width := Self.Width;
  _ownerpanel.Anchors := Self.Anchors;
  _ownerpanel.Align := Self.Align;
  _ownerpanel.BevelOuter := bvNone;
  _ownerpanel.Parent := Self.Parent;
  _ownerpanel.Constraints.Assign(Self.Constraints);

  _statusbar := TStatusBar.Create(_ownerpanel);
  _statusbar.Parent := _ownerpanel;
  _statusbar.SimplePanel := True;
  _statusbar.ShowHint := True;

  Self.Constraints.MaxHeight := 0;
  Self.Constraints.MaxWidth := 0;
  Self.Constraints.MinHeight := 0;
  Self.Constraints.MinWidth := 0;
  Self.Align := alClient;
  Self.Parent := _ownerpanel;

 

21 hours ago, davornik said:

I suppose the next step is to create it like a component and install it in Delphi? Then Panel would be shown in designtime?

Correct. You can play around your component in runtime but to reflect your changes in design time you will need a component installed in the Delphi IDE itself.

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

×