【问题标题】:TStringGrid column resize event?TStringGrid 列调整大小事件?
【发布时间】:2015-02-15 23:00:44
【问题描述】:

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

【问题讨论】:

    标签: delphi tstringgrid


    【解决方案1】:

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

    当列宽改变时响应。

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

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

    【讨论】:

    • 在我看来这不是那么重的操作。你可以像this
    • 我的意思是,我知道该怎么做,但我仍然认为这很麻烦
    【解决方案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;
    

    这是我在 OnMouseUp 事件中为 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;
    

    我认为这是一个比必须继承 TStringGrid 更清洁、更简单的解决方案。

    【讨论】:

      【解决方案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;
      

      【讨论】:

      • 不错!我没有想过这样做,但确实是一个非常干净的解决方案。
      • 不幸的是,它不适用于 Delphi 2007。我不得不用Result := THackGrid (Self).FGridState ; 破解类并编译,但Result := THackGrid (Self).FSizingIndex ; 给出错误:Cannot access private symbol "FSizingIndex"。查看 TCustomGrid 的 VCL 源代码,我看到 FGridState 被声明为 protected 但 FSizingIndex 是 private
      猜你喜欢
      • 2021-06-14
      • 1970-01-01
      • 2011-04-30
      • 1970-01-01
      • 2011-01-13
      • 2019-02-01
      • 2022-10-01
      • 2014-05-31
      相关资源
      最近更新 更多