You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何判断FMX StringGrid中的列是否被调整大小?

Hey there! I’ve dealt with this exact issue before when working with FMX StringGrids—since there’s no built-in OnColumnResized event out of the box, we’ve got a couple of solid workarounds to detect when a column’s width gets adjusted. Let me break them down for you:

Method 1: Track Column Widths with Mouse Events (Quick & Simple)

This approach is great if you want a no-fuss implementation without modifying the grid class. We’ll store the initial column widths, then check for changes when the user releases the mouse (since column resizing happens via dragging the column divider).

First, add a private field to your form to track original widths:

type
  TForm1 = class(TForm)
    StringGrid1: TStringGrid;
    procedure FormCreate(Sender: TObject);
    procedure StringGrid1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single);
  private
    FOriginalColWidths: TArray<Integer>; // Stores initial column widths
  public
    { Public declarations }
  end;

Initialize the width array when the form loads:

procedure TForm1.FormCreate(Sender: TObject);
var
  I: Integer;
begin
  // Initialize array with current column widths
  SetLength(FOriginalColWidths, StringGrid1.ColumnCount);
  for I := 0 to StringGrid1.ColumnCount - 1 do
    FOriginalColWidths[I] := StringGrid1.Columns[I].Width;
end;

Then, check for width changes in the grid’s OnMouseUp event:

procedure TForm1.StringGrid1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Single);
var
  I: Integer;
  CurrentCol: TColumn;
begin
  // Only check left mouse button releases (since that's what's used for resizing)
  if Button = TMouseButton.mbLeft then
  begin
    for I := 0 to StringGrid1.ColumnCount - 1 do
    begin
      CurrentCol := StringGrid1.Columns[I];
      if CurrentCol.Width <> FOriginalColWidths[I] then
      begin
        // Column I was resized! Do your logic here
        ShowMessage(Format('Column %d resized from %d to %d', 
          [I, FOriginalColWidths[I], CurrentCol.Width]));
        
        // Update the stored width to match the new size for future checks
        FOriginalColWidths[I] := CurrentCol.Width;
      end;
    end;
  end;
end;

Notes for Method 1:

  • This will catch resizes even if the user drags the divider back to the original width (but the comparison will just skip triggering your logic in that case).
  • It’s a bit of a brute-force approach since it checks all columns on every mouse up, but it’s perfect for small grids or simple use cases.

Method 2: Subclass TStringGrid for Precise Detection (Cleaner & More Efficient)

If you want a more elegant solution that directly hooks into the grid’s internal resizing logic, subclassing TStringGrid is the way to go. We’ll override the ResizeColumn method (which is called internally when a column’s width is changed) and add a custom event for resizing.

First, create the subclass in your unit:

type
  // Define a custom event type to pass resize details
  TColumnResizedEvent = procedure(Sender: TObject; ACol: Integer; OldWidth, NewWidth: Integer) of object;

  TMyStringGrid = class(TStringGrid)
  private
    FOnColumnResized: TColumnResizedEvent;
    FOldColWidths: TArray<Integer>;
    procedure DoColumnResized(ACol: Integer; OldWidth, NewWidth: Integer);
  protected
    procedure ResizeColumn(ACol: Integer; ANewWidth: Integer); override;
    procedure CreateWnd; override;
  public
    property OnColumnResized: TColumnResizedEvent read FOnColumnResized write FOnColumnResized;
  end;

Implement the subclass methods:

procedure TMyStringGrid.CreateWnd;
var
  I: Integer;
begin
  inherited;
  // Initialize stored widths when the grid is created
  SetLength(FOldColWidths, ColumnCount);
  for I := 0 to ColumnCount - 1 do
    FOldColWidths[I] := Columns[I].Width;
end;

procedure TMyStringGrid.ResizeColumn(ACol: Integer; ANewWidth: Integer);
var
  OldColWidth: Integer;
begin
  OldColWidth := FOldColWidths[ACol];
  // Let the grid handle the resize first
  inherited;
  
  // Only trigger the event if the width actually changed
  if ANewWidth <> OldColWidth then
  begin
    FOldColWidths[ACol] := ANewWidth;
    DoColumnResized(ACol, OldColWidth, ANewWidth);
  end;
end;

procedure TMyStringGrid.DoColumnResized(ACol: Integer; OldWidth, NewWidth: Integer);
begin
  // Fire the custom event if a handler is assigned
  if Assigned(FOnColumnResized) then
    FOnColumnResized(Self, ACol, OldWidth, NewWidth);
end;

Now, replace your form’s TStringGrid with TMyStringGrid (you can do this in the form designer by right-clicking the grid, selecting "Class Name", and entering TMyStringGrid), then assign the custom event:

procedure TForm1.MyStringGrid1ColumnResized(Sender: TObject; ACol: Integer; OldWidth, NewWidth: Integer);
begin
  // Handle the resize event here—you get the exact column and width changes!
  ShowMessage(Format('Column %d resized: %d → %d', [ACol, OldWidth, NewWidth]));
end;

Notes for Method 2:

  • This approach is far more efficient since it only triggers when an actual resize happens, no need to loop through all columns.
  • The custom event gives you direct access to the column index and old/new widths, making it easier to handle specific columns.

内容的提问来源于stack exchange,提问作者R.Nowee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:39:32