2008-12-14 20 views
8

Tôi muốn tạo một điều khiển Danh sách phát. Tôi có rất nhiều thông tin để hiển thị thành một TStringList. Tôi muốn gán một bản ghi cho TStringGrid.Objects thay vì một đối tượng vì rất nhiều đối tượng có thể mất một lúc để tạo/hủy. Nó cũng mất rất nhiều RAM.Tôi muốn chỉ định một bản ghi cho TStringList.Objects

Bản ghi sẽ nhanh hơn và mỏng hơn nhiều. Tôi có thể làm như thế nào?

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

Bạn tạo hồ sơ của mình như thế nào? Sử dụng New (PMyRec) sẽ mất một lượng thời gian tương tự (hoặc bất kỳ phương pháp nào khác tạo ra chúng trên đống) –

Trả lời

1

bạn có thể sử dụng con trỏ bản ghi.

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

Không, bạn không thể làm điều đó. Bản ghi lớn hơn bốn byte. Hình vuông, lỗ tròn. –

+1

Có, bạn có thể. Mỗi Tlist có một đối tượng 4 byte bạn có thể sử dụng cho bất kỳ mục đích nào. Bạn có thể phân bổ bản ghi của mình và đặt đối tượng này làm con trỏ vào bản ghi để bạn có thể dễ dàng tìm thấy nó. Vì vậy, đây là câu trả lời đúng. – lkessler

+0

Bạn sẽ không cần phải chắc chắn rằng bạn đặt bản ghi trên heap thay vì ngăn xếp? Nếu nó ở trên ngăn xếp thì nó sẽ cũ khi nó nằm ngoài phạm vi. –

0

cấp phát bộ nhớ cho bản ghi cũng mất thời gian.

tạo bản ghi của bạn và đặt con trỏ vào đối tượng trong danh sách chuỗi.

6

Bạn có thể sử dụng TList cho một Con trỏ trong hồ sơ của bạn.

Ví dụ:

Type  
PMyrec = ^AMyRec; 

sử dụng

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

vv

{MyList là một danh sách bạn đã tạo ra ở những nơi khác}

MyList.Add(MyRec); 

Bạn sẽ phải xử lý xử lý các mục từ li st ví dụ

Dispose(PMyRec(MyList[Index]));

Để sử dụng một mục từ danh sách:

var 
    MyRec : PMyRec; 

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

vv

1

SOLVED
Tôi đã thử một cái gì đó như thế này bây giờ (dựa trên ví dụ KiwiBastard của):

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; 

+1

Một lần nữa, chỉ cần làm một typecast: PlaylistCtrl.Objects [1,1]: = Pointer (MyRec1); và ngược lại để lấy lại dữ liệu: MyRec: = TMyRec (PlaylistCtrl.Objects [1,1]); –

+0

Một đối tượng lớn hơn bốn byte so với bản ghi tương ứng. Và loại thứ hai của Mike phải là PMyRec chứ không phải TMyRec. –

+0

Vì vậy, việc sử dụng các bản ghi thay vì các đối tượng sẽ "ăn" với cùng một lượng RAM? – Ampere

1

Bạn có chắc chắn muốn phân bổ tất cả các đối tượng đó không? Bằng cách nhìn vào cấu trúc bản ghi có vẻ như bạn muốn một đối tượng trên mỗi hàng - không phải cho mỗi ô. Để làm điều đó, bạn có ít nhất 2 tùy chọn:

  1. (Yêu thích của tôi vì tự do nó cung cấp) Bạn sử dụng TDrawGrid thay thế và vẽ nội dung của ô theo cách thủ công. Nó thực sự không phải là khó!
  2. Bạn tạo một đối tượng đóng gói bản ghi này. Đó là một điều dễ dàng là tốt, ví dụ như:

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; 

Bây giờ bất cứ khi nào bạn muốn để treo lên dữ liệu của mình vào lưới bạn chỉ cần đóng gói nó vào đối tượng đó và sau đó bạn có thể sử dụng bộ sưu tập Objects.

Bây giờ thay vì trải qua tất cả những rắc rối đó, chỉ cần tạo trình xử lý sự kiện cho TDrawGrid.DrawCell như

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

GrdPaths.Canvas.Handle sử dụng với DrawText hoặc nếu Unicode là cần thiết sử dụng DrawTextW (cả hai đến từ Windows API để có tấn ví dụ về cách sử dụng nó) và bạn sẽ giúp bạn và khách hàng của bạn tiết kiệm rất nhiều thất vọng, trí nhớ và trên tất cả - thời gian.

Các vấn đề liên quan