I want to assign a record to TStringList.Objects

[亡魂溺海] 提交于 2020-01-13 08:41:52

问题


I want create a Playlist control. I have a lot of information to display into a TStringList. I want to assign a record to TStringGrid.Objects instead of an object because so many objects may take a while to create/destroy. It also take a lot of RAM.

A record will be much faster and slim. How can I do that?

TYPE
 AMyRec= packed record
        FullName     : string[255];    
        RelativePath : boolean;        
        IsInvalid    : boolean;        
        InCache      : boolean;        
        etc
       end;

回答1:


You can use a TList to a Pointer of your record.

Eg:

Type    
PMyrec = ^AMyRec;

usage

var
   MyRec : PMyRec;
new(MyRec);
MyRec^.Fullname := 'test';
MyRec^.RelativePath := false;

etc

{ MyList is a List you have create elsewhere }

MyList.Add(MyRec);

You'll have to handle disposing of items from the list eg

Dispose(PMyRec(MyList[Index]));

To use an item from the list:

var
  MyRec : PMyRec;

PMyRec := MyList.Items[i];
txtBox.Text = PMyRec^.Fullname;

etc




回答2:


Are you sure you are willing to allocate all those objects? By the look on the record structure it looks like you want an object per row - not per cell. To do that you have at least 2 options:

  1. (My favorite because of the freedom it gives) You use TDrawGrid instead and draw the content of your cell manually. It's really not that hard!
  2. You make an object that encapsulates this record. It's an easy one as well, like for example:

type
  TMyRec= packed record
    FullName     : string[255];
    RelativePath : boolean;
    IsInvalid    : boolean;
  end;
  TMyData = object (TObject)
  private
    FData: TMRec;
  public
    constructor Create(AData: TMyRec);
    property FullName: String read FData.FullName write FData.FullName;
    property RelativePath: Boolean read FData.RelativePath write FData.RelativePath;
    property IsInvalid: Boolean read FData.IsInvalid write FData.IsInvalid;
  end;

...

constructor TMyData.Create(AData: TMyRec);
begin
  FData := AData;
end;

Now whenever you want to hook up your data to the grid you just pack it into that object and you can then use the Objects collection.

Now instead of going through all that hassle just create an event handler for TDrawGrid.DrawCell like

procedure TMainForm.GrdPathsDrawCell(Sender: Object; ...);

use GrdPaths.Canvas.Handle with DrawText or if Unicode is needed use DrawTextW (both come from Windows API so there's tons of examples of how to use it) and you'll save you and your client a lot of frustration, memory and above all - time.




回答3:


you can using the record Pointer.

List.AddObject(MyRecord.FullName, @MyRecord);



回答4:


SOLVED
I have tried something like this now (based on KiwiBastard's example):

Type
 AMyRec= packed record
        FullName     : string[255];
        RelativePath : boolean;
        IsInvalid    : boolean;
       end;
 PMyrec = ^AMyRec;

procedure TPlaylst.Button1Click(Sender: TObject);
VAR MyRec1: PMyRec;
    PlaylistCtrl: TStringGrid;
begin
 {SET}
 new(MyRec1);
 MyRec1^.Fullname := 'test';
 MyRec1^.RelativePath := false;
 PlaylistCtrl.Objects[1,1]:= Pointer(MyRec1); 


 {GET}
 ...
end;




回答5:


allocate the memory for the records takes also time.

create your record and put the pointer to the objects in stringlist.



来源:https://stackoverflow.com/questions/367130/i-want-to-assign-a-record-to-tstringlist-objects

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!