2014-08-28 3 views
-2

Мне нужно внедрить потомком TList элементов управления + дополнительный объект.
что-то вроде:Потомство TList с другим отбоем?

List.Add(AControl, AObject) 

Так Список будет держать как AControl, AObject

Что это лучший способ сделать это с Delphi 7?

+1

Обновление до современных Дельф и и se общий класс классов –

+2

@DavidHeffernan, я знаю об общих классах классов в «современном delphi». Я использую Delphi7, и я не могу обновить. – Vlad

+0

Ты попросил лучшего способа ..... Просто сказал. Вам нужно будет создать некоторый класс в TList, который занимается распределением кучи. Болезненные. Или, возможно, используйте синопсинг синопсиса. –

ответ

10

Вы можете сохранить список записей, то вы можете положить все, что вы хотите в записи, например:

type 
    PMyRecord = ^MyRecord; 
    MyRecord = record 
    Control: TControl; 
    Object: TObject; 
    end; 

var 
    Rec: PMyRecord; 
begin 
    New(Rec); 
    try 
    Rec.Control := AControl; 
    Rec.Object := AObject; 
    List.Add(Rec); 
    except 
    Dispose(Rec); 
    Raise; 
    end; 
end; 

var 
    Rec: PMyRecord; 
begin 
    Rec := PMyRecord(List[SomeIndex]); 
    // use Rec.Control and Rec.Object as needed... 
end; 

Не забудьте Dispose() деталь, когда вы удалите его из списка:

var 
    Rec: PMyRecord; 
begin 
    Rec := PMyRecord(List[SomeIndex]); 
    List.Delete(SomeIndex); 
    Dispose(Rec); 
end; 

А также, когда вы закончите с использованием списка или, по крайней мере, когда вы Clear() это:

var 
    I: Integer; 
    Rec: PMyRecord; 
begin 
    for I := o to List.Count-1 do 
    Dispose(PMyRecord(List[I])); 
    //... 
end; 

Если вы получите новый класс от TList, вы можете изменить свой виртуальный метод Notify() распоряжаться пункты:

type 
    TMyList = class(TList) 
    protected 
    function Get(Index: Integer): PMyRecord; 
    procedure Notify(Ptr: Pointer; Action: TListNotification); override; 
    public 
    function Add(AControl: TControl; AObject: TObject): Integer; 
    procedure Insert(Index: Integer; AControl: TControl; AObject: TObject); 
    property Items[Index: Integer]: PMyRecord read Get; default; 
    end; 

function TMyList.Add(AControl: TControl; AObject: TObject): Integer; 
var 
    Rec: PMyRecord; 
begin 
    New(Rec); 
    try 
    Rec.Control := AControl; 
    Rec.Object := AObject; 
    Result := inherited Add(Rec); 
    except 
    Dispose(Rec); 
    Raise; 
    end; 
end; 

procedure TMyList.Insert(Index: Integer; AControl: TControl; AObject: TObject); 
var 
    Rec: PMyRecord; 
begin 
    New(Rec); 
    try 
    Rec.Control := AControl; 
    Rec.Object := AObject; 
    inherited Insert(Index, Rec); 
    except 
    Dispose(Rec); 
    Raise; 
    end; 
end; 

function TMyList.Get(Index: Integer): PMyRecord; 
begin 
    Result := PMyRecord(inherited Get(Index)); 
end; 

procedure TMyList.Notify(Ptr: Pointer; Action: TListNotification); 
begin 
    inherited; 
    if Action = lnDeleted then 
    Dispose(PMyRecord(Ptr)); 
end; 
+2

Или используйте 'TObjectList', если он забыт –

+2

Это будет работать, если вы создадите новый класс вместо записи для хранения значений списка. Лично я считаю, что дополнительный класс будет лишним накладными расходами. –

+0

Это было бы самое простое решение. Для записи нужно было бы получить новый класс и переопределить Notify, чтобы сделать его удобным. Ах, я вижу, вы это продемонстрировали. Лучше. +1 –

1

попробовать это

type 
    TForm1 = class(TForm) 
    Button1: TButton; 
    procedure Button1Click(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

    TMyContainer = class 
    public 
    ctnGen: TControl; 
    objGen: TObject; 
    constructor Create(const ctnGen: TControl; const objGen: TObject); 
    end; 

var 
    Form1: TForm1; 

implementation 

uses 
    Contnrs; 

{$R *.DFM} 

{ TMyContainer } 

constructor TMyContainer.Create(const ctnGen: TControl; 
    const objGen: TObject); 
begin 
    inherited Create(); 
    Self.ctnGen := ctnGen; 
    Self.objGen := objGen; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    lstGen: TObjectList; 
begin 
    lstGen := TObjectList.Create(True); 
    try 
     lstGen.Add(TMyContainer.Create(Self, Self)); 
     ShowMessage(TMyContainer(lstGen.Items[0]).objGen.ClassName); 
    finally 
     lstGen.Free; 
    end;           
end; 

TObjectList освободит класс TMyContainer

+3

Добро пожаловать в рай для утечек. Возможно, TObjectList решит это. –

+1

@ Vlad код был изменен – Passella

Смежные вопросы