davornik 4 Posted October 30 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)? Share this post Link to post
aehimself 396 Posted Thursday at 08:27 AM (edited) 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 Thursday at 08:31 AM by aehimself Share this post Link to post
davornik 4 Posted Saturday at 10:57 AM 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
rvk 32 Posted Saturday at 12:11 PM 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
aehimself 396 Posted Sunday at 08:43 AM 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