Search code examples
delphicomponentsextend

Adding functionalities to a column of a StringGrid in delphi


So I have a string grid with columns. But each column can be deleted and if a column is deleted indexes are rearranged. I can use the value of my index before deletion, but when it comes to delete several columns the indexes aren't the same at all. For example if i delete the column at index 1 and 2, the one that was at index 3 get a new index, index 1.

So what I want to do is to add new methods to my columns where i will set and get the real index, as it was never deleted. I have found a tutorial on how to add new methods to delphi classes and this is how it looks:

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.

This works if i use it to add methods on a StringGrid. But i want to use this on a Column of a stringGrid. I've seen that some methods are coming from the class TStrings or TObject, and i tried them both but the procedure hello doesn't show.

EDIT

Using class helper i managed to have access to my own method and after changing this is how it looks:

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.

Thing is that if i add a private statement i can't use my methods anymore which are declared in public statement. And when i set a value it's actually the same for all columns. This is how i uses this class:

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

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

And then all the value for any column is always the same. When i'm setting my values they are different each time. But getting them, returns me always the last value i inserted using setValue method.


Solution

  • Regarding to your edit, you have got one variable so any access to your helper will read/write on this.

    Although it is possible to save the index of a Col with a helper class , it does not really help because the "content" of a col is "moved" to another one.
    Internal cols is a casted Pointer to an entry in an TSparsePointerArray of a TSparseList

    Below standing code is not meant to build such a helper as a recommendation, but for illustrative purposes only.

    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;
    

    The result if we delete Col 1 and Col 2:

    enter image description here