I want to have a button with icon at the end of each row.
Like here:
I tried this
procedure TMyFrame.sgrd1DrawCell(Sender: TObject; ACol,
ARow: Integer; Rect: TRect; State: TGridDrawState);
var
canvas: TCanvas;
sgrd: TStringGrid;
point: TPoint;
btn: TSpeedButton;
begin
sgrd := TStringGrid(Sender);
canvas := sgrd.Canvas;
canvas.FillRect(Rect);
if (ACol = 1) then
begin
point := Self.ScreenToClient(ClientToScreen(Rect.TopLeft));
btn := TSpeedButton.Create(sgrd);
btn.Parent := sgrd;
btn.OnClick := SpeedButton1Click;
btn.Tag := ARow;
btn.enabled:=true;
btn.visible:= true;
btn.Top := point.Y;
btn.Left := point.X;
btn.Width := 20;
btn.Height := 24;
end;
end;
but the button doesn't look like "alive" although click event works. No click, hover animation, focus, etc.
The problem is that you are continuously creating a new speedbutton every time the cell needs refreshing. You must create the buttons in the Create event.
Assuming you might want to be able to scroll within your StringGrid and have the Buttons beeing associated with the selected row, you will have to implement an handler for TopLeftChanged. The buttons won't be moved if you scroll in your Stringgrid, without implementing code for this.
an enhanced version as suggested by @Tlama would make it necessary to implement an interposer class or use an own component to override ColWidthsChanged and RowHeightsChanged to keep the buttons painted correct not just on scrolling but on row/column sizing.