2006. november 30., csütörtök

Create a TStringGrid with one column of runtime created buttons in it


Problem/Question/Abstract:

I want the following: A StringGrid with 1 column of buttons in it. The number of rows in the grid is not known at design time, so the buttons are created at runtime.

Answer:

TSpeedButton will work and you won't have to worry about the TabStop. The problem with using the Rect that comes in as a param, it doesn't hit all the cells in the column. So what you end up with is buttons displaying in the wrong cells. If it doesn't matter, then you're ok. But if it does, then you'll need to update the entire column for all the visible cells. Here's what I came up with:

{ ... }
var
  HelpButtons: array of TSpeedButton;

procedure Form1.CreateTheButtons;
var
  i: Integer;
begin
  SetLength(HelpButtons, ParamGrid.RowCount - 1);
  for i := 0 to ParamGrid.RowCount - 2 do
  begin
    HelpButtons[i] := TSpeedButton.Create(Self);
    HelpButtons[i].Visible := False;
    HelpButtons[i].Parent := ParamGrid;
    HelpButtons[i].Caption := IntToStr(i) + ' ?';
    HelpButtons[i].Width := 34;
    HelpButtons[i].Height := 18;
    HelpButtons[i].Tag := i;
    HelpButtons[i].OnClick := ParamGridButtonClick;
  end;
  {Force the buttons to show}
  ParamGrid.Refresh;
end;

procedure TForm1.ParamGridDrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);

  procedure UpdateTheColumn;
  var
    i: Integer;
    R: TRect;
  begin
    for i := ParamGrid.TopRow to (ParamGrid.VisibleRowCount + ParamGrid.TopRow) do
    begin
      if i >= ParamGrid.RowCount then
        Break;
      R := ParamGrid.CellRect(2, i);
      HelpButtons[i - 1].Top := R.Top;
      HelpButtons[i - 1].Left := R.Left;
      if not HelpButtons[i - 1].Visible then
        HelpButtons[i - 1].Visible := True;
    end;
  end;

begin
  if Length(HelpButtons) = 0 then
    Exit;
  if not FRefresh then
    Exit;
  if ((ACol = 2) and (ARow > 0)) then
  begin
    UpdateTheColumn;
  end;
end;

procedure TForm1.ParamGridButtonClick(Sender: TObject);
begin
  ShowMessage('Click ' + Sender.ClassName + ' ' + IntToStr(TControl(Sender).Tag));
end;

Nincsenek megjegyzések:

Megjegyzés küldése