2
votes

TStringGrid has a TGridOption goColSizing that allows for automatic resizing of columns at runtime when you drag in the margin between the columns. Is there a corresponding event that is triggered when a column size occurs? I'd like to resize another component to match the size/location of a certain column should the column sizes change.

3

3 Answers

3
votes

So far as I can tell, no event is surfaced to notify you of such a modification. I think that the best you can do is to sub-class the control and override the ColWidthsChanged method:

Responds when the column widths change.

ColWidthsChanged is called immediately after the column widths change. The change can result from setting the ColWidths property, from setting the DefaultColWidth property, from moving one of the columns, or from resizing the columns with the mouse.

Since sub-classing a control is a very heavy weight operation, it might be prudent to sub-class once and override this method in order to surface an event.

2
votes

Maybe I'm a little late with my answer but I stumbled upon the same problem and have found an easier solution if you'd rather not subclass TStringGrid. My solution involves using Rtti in the OnMouseUp event to retrieve the value of the protected field FGridState from TCustomGrid.

Note that I have my own Rtti class with some class functions that make it easier to use Rtti throughout my program code.

class function TRttiUtils.GetClassField(aClass: TClass;
  aFieldName: String): TRttiField;
var
  Fields: TArray<TRttiField>;
  Field: TRttiField;
begin
  Result := nil;

  Fields := GetClassFields(aClass);

  For Field in Fields do
    If Field.Name = aFieldName
    then begin
      Result := Field;
      break;
    end;
end;

class function TRttiUtils.GetClassFields(aClass: TClass): TArray<TRttiField>;
var
  RttiContext: TRttiContext;
  RttiType: TRttiInstanceType;
  Fields: TArray<TRttiField>;
begin
  RttiContext := TRttiContext.Create;
  RttiType := RttiContext.GetType(aClass) as TRttiInstanceType;
  Fields := RttiType.GetFields;

  Result := Fields;
end;

These are the two class functions that I use in my OnMouseUp event for the stringgrid.

procedure TFrameCurrency.sgCurrenciesMouseUp(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
  R: TPoint;
  Row, Col: Integer;
  GridStateField: TRttiField;
  GridState: TGridState;
  ColSizing: Boolean;
begin
  inherited;

  If Button = mbLeft
  then begin
    //Determine row and column
    (Sender As TStringGrid).MouseToCell(X, Y, R.X, R.Y);
    Row := R.Y;
    Col := R.X;

    //Check if it is ColSizing
    ColSizing := False;

    GridStateField := TRttiUtils.GetClassField(TStringGrid, 'FGridState');
    If Assigned(GridStateField)
    then begin
      GridState := GridStateField.GetValue(sgCurrencies).AsType<TGridState>;
      If GridState = gsColSizing
      then begin
        //specific code comes here

        ColSizing := True;
      end;
    end;

    If Not ColSizing
    then begin
      //sorting logic comes here
    end;
  end;
end;

I think this is a cleaner and easier solution than having to subclass TStringGrid.

2
votes

I have found another solution that is even easier, one that relies on a Delphi oddity: helper functions get private access. If we define helper class for TCustomerGrid (we have to 'help' TCustomGrid rather than TStringGrid because that is where the private fields are):

TCustomGridHelper = class helper for TCustomGrid
  function GetGridState : TGridState;
  function GetSizingIndex : Integer;
end;

function TCustomGridHelper.GetGridState: TGridState;
begin
  Result := Self.FGridState;
end;

function TCustomGridHelper.GetSizingIndex: Integer;
begin
  Result := Self.FSizingIndex;
end;

Now, to use it we just do:

procedure TSomeForm.ProductAllowedGridMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
  col, row: Integer;
  grid: TStringGrid;
begin
  if Button = mbLeft then begin
    grid := TStringGrid(Sender);
    if grid.GetGridState = gsColSizing then begin
      // display column and new size
      Caption := IntToStr(grid.GetSizingIndex) + ': ' + IntToStr(grid.ColWidths[grid.GetSizingIndex]);
    end;
  end;
end;