0

I'm adding a ControlButton on a TDBGrid descendant.

type TAEDBGrid = class(TDBGrid)
  private
    ControlButton: TButton;
    procedure ControlButton_Click(Sender: TObject);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
end

constructor TAEDBGrid.Create(AOwner: TComponent);
var Menu: TPopupMenu;
    Item: TMenuItem;
begin
    inherited Create(AOwner);

    ControlButton := TButton.Create(nil);
    ControlButton.Caption := '...';
    ControlButton.Font.Style := Self.Font.Style + [fsBold];
    ControlButton.Top := Self.Top + 1;
    ControlButton.Left := Self.Left + 1;
    ControlButton.Height := 19;
    ControlButton.Width := 17;
    ControlButton.Parent := Self.Parent;
    ControlButton.OnClick := ControlButton_Click;

    Menu := TPopupMenu.Create(ControlButton);
    Item := TMenuItem.Create(Menu);
    Item.Caption := 'Select Columns';
    Item.OnClick := ControlButton_SelectColumns;
    Menu.Items.Add(Item);
    Item := TMenuItem.Create(Menu);
    Item.Caption := 'Export to Excel';
    Item.OnClick := ControlButton_ExportToExcel;
    Item.Visible := False;
    Menu.Items.Add(Item);
    ControlButton.PopupMenu := Menu;
end;

destructor TAEDBGrid.Destroy;
begin
    ControlButton.Free;

    inherited Destroy;
end;

procedure TAEDBGrid.ControlButton_Click(Sender: TObject);
var Position: TPoint;
begin
  if GetCursorPos(Position) then ControlButton.PopupMenu.Popup(Position.X, Position.Y);
end;

The problem is that at the moment that I create the ControlButton, the Self.Top, Self.Left properties are 0, and Self.Parent is nil. So my button gets no parent and is not visible.

What method should I override to create my button where the Grid parent has already been assigned ?. I've tried AfterConstruction, with the same problem.

The best alternative I've found is overriding SetFocus and checking not Assigned(ControlButton), but it only creates the button when the user gets into the grid.

Thank you.

Marc Guillot
  • 6,090
  • 1
  • 15
  • 42
  • Personally, I would start with the AfterScroll event of the dataset feeding the grid, because its the dataset which determines the active row of the grid. – MartynA Oct 05 '21 at 16:23
  • Thanks Martyn, but I want to program it on my Grid descendant, so I don't have to replicate it on every grid. On the constructor of the grid you would replace the AfterScroll of its Datasource.Dataset in order to create that button and call back the original event handler ?. Seems a bit too convoluted. – Marc Guillot Oct 05 '21 at 16:34

2 Answers2

1

You can try override Loaded method:

protected
{ Protected declarations }
procedure Loaded; override;

And do initialization of your child controls inside.

  • Thanks Miroslav, but I followed Tom suggestion on the comments and now it works correctly, on the Constructor itself. I was assigning the wrong Parent. – Marc Guillot Oct 06 '21 at 10:11
1

If you want the grid to be the parent of the button, then you should write

ControlButton.Parent := Self; //(and not Self.Parent)

since you are in the constructor of the grid.

Tom Brunberg
  • 20,312
  • 8
  • 37
  • 54