TStringGrid 列调整大小事件?

问题描述 投票:0回答:4

TStringGrid
有一个 TGridOption
goColSizing
,当您拖动列之间的边距时,可以在运行时自动调整列的大小。当列大小发生时是否有相应的事件被触发?如果列大小发生变化,我想调整另一个组件的大小以匹配特定列的大小/位置。

delphi tstringgrid
4个回答
3
投票

据我所知,没有任何事件通知您此类修改。我认为你能做的最好的事情就是对控件进行子类化并覆盖

ColWidthsChanged
方法:

当列宽改变时做出响应。

ColWidthsChanged 在列宽更改后立即调用。更改可以通过设置 ColWidths 属性、设置 DefaultColWidth 属性、移动其中一列或使用鼠标调整列大小来实现。

由于对控件进行子类化是一项非常繁重的操作,因此谨慎的做法可能是对控件进行子类化并重写此方法以显示事件。


3
投票

我发现了另一种更简单的解决方案,它依赖于 Delphi 的一个奇怪之处:辅助函数获得私有访问。如果我们为 TCustomerGrid 定义帮助程序类(我们必须“帮助”TCustomGrid 而不是 TStringGrid,因为那是私有字段所在的位置):

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;

现在,要使用它,我们只需:

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;

2
投票

也许我的回答有点晚了,但我偶然发现了同样的问题,并且如果您不想继承 TStringGrid 的子类,则找到了更简单的解决方案。 我的解决方案涉及在 OnMouseUp 事件中使用 Rtti 从 TCustomGrid 检索受保护字段 FGridState 的值。

请注意,我有自己的 Rtti 类,其中包含一些类函数,可以更轻松地在整个程序代码中使用 Rtti。

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;

这些是我在 stringgrid 的 OnMouseUp 事件中使用的两个类函数。

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;

我认为这是一个比必须子类化 TStringGrid 更干净、更简单的解决方案。


0
投票

基于 jdetaeye 发布的内容,为了支持 TDBGrids,我发现 MouseToCell 不可靠,并通过以下修改解决了它。

procedure TForm.DBGridMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  if Button <> mbLeft then
    Exit;

  var GridStateField := TRttiUtils.GetClassField(TCustomGrid, 'FGridState');
  if GridStateField=nil then
    Exit;
  if GridStateField.GetValue(Sender).AsType<TGridState> <> gsColSizing then
    Exit;

  var SizingIndexField := TRttiUtils.GetClassField(TCustomGrid, 'FSizingIndex');
  if SizingIndexField=nil then
    Exit;
  var Col:=SizingIndexField.GetValue(Sender).AsType<LongInt>;

  OutputDebugString(PChar('Sizing Column '+Col.ToString));
end;
© www.soinside.com 2019 - 2024. All rights reserved.