在delphi中向StringGrid的列添加功能

时间:2014-09-24 07:08:32

标签: delphi components extend

所以我有一个带有列的字符串网格。但是可以删除每列,如果删除列,则重新排列索引。我可以在删除之前使用索引的值,但是当删除多个列时,索引根本就不相同。例如,如果我删除索引1和2处的列,则索引为3的列将获得一个新索引,索引为1。

所以我想要做的是在我的列中添加新方法,我将设置并获取真正的索引,因为它从未被删除。我找到了一个关于如何向delphi类添加新方法的教程,这就是它的外观:

unit columnInterceptor

interface

uses stdCtrls, sysUtils, Classes, dialogs, grids;

type
   TStrings = class(Classes.TStrings)
   private
   public
     procedure hello;
   end;

implementation

procedure TStrings.Hello;
begin
    ShowMessage('hello');
end;
end.

如果我使用它在StringGrid上添加方法,这是有效的。但我想在stringGrid的列上使用它。我已经看到一些方法来自TStrings或TObject类,我试过它们但是程序你好并没有显示出来。

修改

使用类帮助程序我设法可以访问我自己的方法,在更改之后它的外观如下:

unit columnInterceptor

interface
uses stdCtrls, sysUtils, Classes, dialogs, grids;

type
   colIntercept= class helper for TStrings
   public
     procedure setValue(val: integer);
     function getValue: integer;
   end;

implementation
var 
  value : integer;


procedure colIntercept.setValue(val: integer);
begin
    value := integer;;
end;
function colIntercept.getValue: integer;
begin
    Result := value;
end;
end.

事情是,如果我添加一个私人声明,我不能再使用我的方法,这些方法在公共声明中声明。当我设置一个值时,它对所有列实际上是相同的。这是我使用这个类的方式:

//somewhere in the unit where  create all the columns
grid.Cols[aCol].setValue(aCol);

//somewhere in the unit
grid.Cols[aCol].getValue

然后任何列的所有值都始终相同。当我设定我的价值时,他们每次都是不同的。但是获取它们,总是返回我使用setValue方法插入的最后一个值。

2 个答案:

答案 0 :(得分:0)

问题是StringGrid.Cols不是TStrings而是TStrings的后代。

您可以尝试以下代码:

ShowMessage(StringGrid1.Cols[0].Classname);

然后你会发现真正的类是TStringGridStrings

因此,这引出了解决方案:

为TStringGridStrings写一个classhelper

type
  TStringGridStringsHelper = class helper for TStringGridStrings
    procedure SayHello;
  end;

{ TStringGridStringsHelper }

procedure TStringGridStringsHelper.SayHello;
begin
  ShowMessage('Hello from TStringGridStringsHelper');
end;

但仍然无法写

StringGrid1.Cols[0].SayHello;

你必须对它进行类型转换:

TStringGridStrings(StringGrid1.Cols[0]).SayHello;

问题是StringGrid只将它的列公开为TStrings,而不是正确的数据类型TStringGridStrings,这就是你必须输入它的原因

<强> =====================

另一个解决方案可能是使用检查员类(http://delphi.about.com/od/delphitips2009/qt/interceptor.htm),但有些人说这是错误的代码:

以下是示例:

unit Unit6;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, Grids;

type
  TStringGridStringsHelper = class helper for TStringGridStrings
    procedure SayHello;
  end;

  TStringGrid = class(Grids.TStringGrid)
  strict private
    function GetCols(Index: Integer): TStringGridStrings;
    function GetRows(Index: Integer): TStringGridStrings;
    procedure SetCols(Index: Integer; const Value: TStringGridStrings);
    procedure SetRows(Index: Integer; const Value: TStringGridStrings);
  public
    property Cols[Index: Integer]: TStringGridStrings read GetCols write SetCols;
    property Rows[Index: Integer]: TStringGridStrings read GetRows write SetRows;
  end;

  TForm6 = class(TForm)
    StringGrid1: TStringGrid;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form6: TForm6;

implementation

{$R *.dfm}

uses
  Math;

{ TStringGridStringsHelper }

procedure TStringGridStringsHelper.SayHello;
begin
  ShowMessage('Hello from TStringGridStringsHelper');
end;

procedure TForm6.FormCreate(Sender: TObject);
begin
  StringGrid1.Rows[0].SayHello;
end;

{ TMyStringGrid }

function TStringGrid.GetCols(Index: Integer): TStringGridStrings;
begin
  Result := inherited Cols[Index] as TStringGridStrings;
end;

function TStringGrid.GetRows(Index: Integer): TStringGridStrings;
begin
  Result := inherited Rows[Index] as TStringGridStrings;
end;

procedure TStringGrid.SetCols(Index: Integer; const Value: TStringGridStrings);
begin
  inherited Cols[Index] := Value;
end;

procedure TStringGrid.SetRows(Index: Integer; const Value: TStringGridStrings);
begin
  inherited Rows[Index] := Value;
end;

end.

答案 1 :(得分:0)

关于你的编辑,你有一个变量,所以对你的帮助者的任何访问权都可以读/写。

虽然可以使用帮助程序类保存Col的索引   ,它并没有真正帮助,因为col的“内容”被“移动”到另一个   内部cols是指向TSparseList的TSparsePointerArray中的条目的指针指针

以下代码并不意味着建立这样的帮助作为推荐,但仅用于说明目的。

implementation
uses system.generics.collections;

{$R *.dfm}
type
   THackGrid=Class(TCustomGrid);



  TSLDict=Class(TDictionary<TStrings,Integer>)
  End;

  TStringsHelper = class helper for TStrings
   private
    class var Dict:TSLDict;
    function GetIndex: Integer;
    procedure SetIndex(const Value: Integer);
   public
    CLASS Procedure FreeDict;
    Property Index:Integer Read GetIndex write SetIndex;

  end;



{ TStringsHelper }

CLASS procedure TStringsHelper.FreeDict;
begin
  FreeAndNil(Dict);
end;

function TStringsHelper.GetIndex: Integer;
begin
   if not assigned(Dict) then Dict:=TSLDict.Create;
   if not Dict.TryGetValue(self,Result) then Result := -1;

end;

procedure TStringsHelper.SetIndex(const Value: Integer);
begin
   if not assigned(Dict) then Dict:=TSLDict.Create;
   Dict.AddOrSetValue(self,Value);
end;


procedure TForm7.DeleteAColClick(Sender: TObject);
var
 I:Integer;
begin
  for I := 0 to StringGrid1.ColCount - 1 do
  begin
      StringGrid1.Cells[i,0] := IntToStr(i);
      StringGrid2.Cells[i,0] := IntToStr(i);
      StringGrid1.Cols[i].Index := i;

  end;

  for I := 0 to StringGrid1.ColCount - 1 do
  begin
      StringGrid1.Cells[i,1] := IntToStr(StringGrid1.Cols[i].Index);
      StringGrid1.Cells[i,2] := '$'+IntToHex(Integer(StringGrid1.Cols[i]),8);
      StringGrid2.Cells[i,1] := IntToStr(StringGrid1.Cols[i].Index);
      StringGrid2.Cells[i,2] := '$'+IntToHex(Integer(StringGrid1.Cols[i]),8);

  end;

  THackGrid(StringGrid1).DeleteColumn(2);
  THackGrid(StringGrid1).DeleteColumn(1);
  for I := 0 to StringGrid1.ColCount - 1 do
  begin
      StringGrid1.Cells[i,3] := IntToStr(StringGrid1.Cols[i].Index);
      StringGrid1.Cells[i,4] := '$'+IntToHex(Integer(StringGrid1.Cols[i]),8)
  end;
end;


procedure TForm7.MoveAColClick(Sender: TObject);
var
 I:Integer;
begin
  for I := 0 to StringGrid1.ColCount - 1 do
  begin
      StringGrid1.Cells[i,0] := IntToStr(i);
      StringGrid2.Cells[i,0] := IntToStr(i);
      StringGrid1.Cols[i].Index := i;
  end;

  for I := 0 to StringGrid1.ColCount - 1 do
  begin
      StringGrid1.Cells[i,1] := IntToStr(StringGrid1.Cols[i].Index);
      StringGrid1.Cells[i,2] := '$'+IntToHex(Integer(StringGrid1.Cols[i]),8);
      StringGrid2.Cells[i,1] := IntToStr(StringGrid1.Cols[i].Index);
      StringGrid2.Cells[i,2] := '$'+IntToHex(Integer(StringGrid1.Cols[i]),8);
  end;

 THackGrid(StringGrid1).MoveColumn(0,3);
  for I := 0 to StringGrid1.ColCount - 1 do
  begin
      StringGrid1.Cells[i,3] := IntToStr(StringGrid1.Cols[i].Index);
      StringGrid1.Cells[i,4] := '$'+IntToHex(Integer(StringGrid1.Cols[i]),8)
  end;
end;


procedure TForm7.MoveFirstAndDeleteThenClick(Sender: TObject);
var
 I:Integer;
 // we want to delete Col 1
begin
  for I := 0 to StringGrid1.ColCount - 1 do
  begin
      StringGrid1.Cells[i,0] := IntToStr(i);
      StringGrid1.Cols[i].Index := i;
  end;

  for I := 0 to StringGrid1.ColCount - 1 do
  begin
      StringGrid1.Cells[i,1] := IntToStr(StringGrid1.Cols[i].Index);
  end;

  THackGrid(StringGrid1).MoveColumn(1,StringGrid1.ColCount-1);
  THackGrid(StringGrid1).DeleteColumn(StringGrid1.ColCount-1);
  for I := 0 to StringGrid1.ColCount - 1 do
  begin
      StringGrid1.Cells[i,2] := IntToStr(StringGrid1.Cols[i].Index);
  end;
end;

initialization
finalization
 TStrings.FreeDict;

如果我们删除Col 1和Col 2的结果:

enter image description here