问题
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:
- (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!
- 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