![]() |
Freigeben vom Propertys aus Generics..Tlist<tcontrol> gelingt nicht
Hi Comm,
habe ein Problem beim "Nachempfinden" von Components oder controls. Propertys sollen in eine Generics.collections.tlist<tcontrol> eingeschrieben und verwaltet werden Die Propertys werden unter bestimmten umständen nicht "gelöscht". Funktionierendes Beispiel:
Delphi-Quellcode:
Ich schreibe FormRichEd und FormMemo ein eine Liste und lösche sie dann per Button. Wenn ich beide Buttons betätigt habe, zeigt procedure TForm1.showListinfos folgendes:
type
TForm1 = class(TForm) MainMenu1: TMainMenu; FormRiched: TRichEdit; Formmemo: TMemo; DelformRiched: TButton; DelFormMemo: TButton; RichEdit2: TRichEdit;//zum Anzeigen procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure DelformRichedClick(Sender: TObject); procedure DelFormMemoClick(Sender: TObject); private FList: Tlist<tcontrol>; { Private-Deklarationen } property List: Tlist<tcontrol> read FList write FList; public { Public-Deklarationen } procedure showListinfos; end; //erzeugen der Liste procedure TForm1.FormCreate(Sender: TObject); begin list:=tlist<tcontrol>.Create; list.Add(FormRiched); list.Add(FormMemo); end; //freigeben der Liste procedure TForm1.FormDestroy(Sender: TObject); begin freeandnil(flist); end; procedure TForm1.DelformRichedClick(Sender: TObject); begin if assigned(list.items[0]) then begin list.items[0].free; //freeandnil(list.items[0]) geht nicht list.items[0]:=nil; //sonst zeigt der Listeneintrag noch auf "Etwas" ?, beim Erneuten aufrufen dieser Procedure Fehler end; showListinfos; end; procedure TForm1.DelFormMemoClick(Sender: TObject); begin if assigned(list.items[1]) then begin list.items[1].free; //freeandnil(list.items[0]) geht nicht list.items[1]:=nil; end; showlistinfos; end; // zeigt, was noch assigned ist procedure TForm1.showListinfos; var I: Integer; begin RichEdit2.Clear; for I := 0 to list.count-1 do begin if Assigned(list.items[i]) then richedit2.Lines.add('Eintrag '+inttostr(i)+' is ASSIGNEd' ) else richedit2.Lines.add('Eintrag '+inttostr(i)+' is NOT ASSIGNEd' ) end; if assigned(FormRiched) then richedit2.Lines.add('FormRiched '+' is ASSIGNEd' ) else richedit2.Lines.add('FormRiched '+' is NOT ASSIGNEd' ); if assigned(Formmemo) then richedit2.Lines.add('FormMemo is ASSIGNEd' ) else richedit2.Lines.add('FormeMemo is NOT ASSIGNEd' ) end; Eintrag 0 is NOT ASSIGNEd Eintrag 1 is NOT ASSIGNEd FormRiched is NOT ASSIGNEd FormeMemo is NOT ASSIGNEd würde ich in der liste die Einträge nicht =NIL setzen, sieht es so aus: Eintrag 0 is ASSIGNEd Eintrag 1 is ASSIGNEd FormRiched is NOT ASSIGNEd FormeMemo is NOT ASSIGNEd also die Liste zeigt noch auf etwas. (wenn man über die Liste auf die Propertys versuchen würde, zu zugreifen - ist ja assigned - gibt's Fehler) Aber die Propertays FormRichEd und Formmemo wurden ordnungsgemäß freigegeben und von wem auch immer auf nil gesetzt. Nun Der PROBLEMFALL als verkürztes Beispiel: Ein z.b. tRichedit soll als Propertys einen tRichedit und ein tmemo verwalten. Und diese sollen auch über eine eigenen Liste verwaltet werden
Delphi-Quellcode:
type
tShowOpt_UA =(ShowOwnRichEd_UA, ShowOwnMemo_UA,ShowOwnHeadContr_UA,ShowOwnstatBar_UA, ShowDeleteOwnComps_UA); tShowOpts_UA = set of tShowOpt_UA; TTestRich_UA = class(TRichedit) private { private declarations } FOwnRichEd: trichedit; FOwnMemo: tmemo; FOwnControlList: tlist<TControl>;// geht so nicht zum löschen? protected { protected declarations } procedure SetParent(AParent: TWinControl); override;//hier wird Parent Von testrich gesetzt und und man kann z.b. Top und left von den Own-Komponenten setzen public { public declarations } property OwnControlList: tlist<TControl> read FOwnControlList write FOwnControlList;//die Verwaltungsliste published { published declarations } property OwnRichEd: trichedit read FOwnRichEd write FOwnRichEd; property OwnMemo: tmemo read FOwnMemo write FOwnMemo; constructor Create(AOwner:TComponent);override; procedure CreateOwnComps(SO: tshowopt_UA);virtual;//hier wird je nach Anforderung OwnRiched und OwnMemo erzeugt procedure CreateOwnRichEd;virtual;// Routine für OwnRiched procedure CreateOwnMemo;virtual;// Routine für OwnMemo destructor destroy;override;//die Liste wieder löschen procedure expresscontrols;virtual;//Onwriched und OwnMemo Parent zuteilen - Darstellung auf der Form procedure SetParentDepOwnProps(SO: tshowopt_UA);virtual;//das Berechnen, was vor dem Setzen von Riched.parent nicht mgl. war end; { TTestRich_UA } constructor TTestRich_UA.Create(AOwner: TComponent); var so:tshowopt_UA; I: Integer; begin inherited; OwnControlList:=tlist<TControl>.create; OwnRichEd:=nil; OwnMemo:=nil; for so := Low(tshowopt_UA) to High(tshowopt_UA) do CreateOwnComps(so); for I := 0 to componentcount-1 do if components[i] is tcontrol then OwnControlList.add(tcontrol(components[i])); { entspricht oben with OwnControlList do begin add(FOwnRichEd); add(FOwnMemo); end; } end; procedure TTestRich_UA.CreateOwnComps(SO: tshowopt_UA); begin case so of ShowOwnRichEd_UA: CreateOwnRichEd; ShowOwnMemo_UA: CreateOwnMemo; end; end; procedure TTestRich_UA.CreateOwnMemo; begin if not Assigned(OwnMemo) then begin OwnMemo:=tmemo.create(self); with OwnMemo do begin name:='OwnMemo'; SetSubComponent(true); width:=Width div 2; Height:=height; if self.parent=nil then parent:=self else begin parent:=self.parent; //zur laufzeit erzeugt SetParentDepOwnProps(ShowOwnMemo_UA);//dann auch top und left berechnen end; Show; end; end else OwnMemo.show; end; procedure TTestRich_UA.CreateOwnRichEd; begin if not Assigned(OwnRichEd) then begin OwnRichEd:=trichedit.create(self); with OwnRichEd do begin name:='OwnRiched'; SetSubComponent(true); width:=Width div 2; Height:=height; if self.parent=nil then parent:=self else begin parent:=self.parent; //zur laufzeit erzeugt SetParentDepOwnProps(ShowOwnRichEd_UA);//dann auch top und left berechnen end; Show; end; end else ownriched.show; end; destructor TTestRich_UA.destroy; begin freeandnil(fOwnControlList); inherited; end; procedure TTestRich_UA.expresscontrols; var i:integer; begin for I := 0 to componentcount-1 do begin if components[i] is tcontrol then begin tcontrol(components[i]).parent:=self.parent; SetParentDepOwnProps(tshowopt_UA(i)); end; end; end; procedure TTestRich_UA.SetParent(AParent: TWinControl); begin inherited;//parent wird gestzt if not (csDestroying in ComponentState) then // wenn nicht gerade in in auflösung expresscontrols; end; procedure TTestRich_UA.SetParentDepOwnProps(SO: tshowopt_UA); Procedure CalcOwnrichEd; begin if assigned(OwnRichEd) then with OwnRichEd do begin top:=self.top; left:=self.left+self.Width; end; end; Procedure CalcOwnMemo; begin if assigned(OwnMemo) then with Ownmemo do begin top:=self.top; left:=self.left-Width; end; end; begin case so of ShowOwnRichEd_UA: CalcOwnrichEd; ShowOwnMemo_UA: CalcOwnMemo; end; Wenn ich nun wie im funktionierenden Beispiel OwnRiched und OwnMemo via FOwnControlLis lösche und Nil setze,
Delphi-Quellcode:
procedure TForm1.Button3Click(Sender: TObject);
begin if assigned(TestRich_UA1.OwnControlList.items[0]) then begin TestRich_UA1.OwnControlList.items[0].free; TestRich_UA1.OwnControlList.items[0]:=nil;// ohne Nil setzen zeigt der Listeneintrag noch auf etwas end; showOwnListinfos; end; procedure TForm1.Button4Click(Sender: TObject); begin if assigned(TestRich_UA1.OwnControlList.items[1]) then begin TestRich_UA1.OwnControlList.items[1].free; TestRich_UA1.OwnControlList.items[1]:=nil;// ohne Nil setzen zeigt der Listeneintrag noch auf etwas end; showOwnListinfos; end; ergibt die Prüfung auf Assigned folgendes: Eintrag 0 is NOT ASSIGNEd Eintrag 1 is NOT ASSIGNEd ownRiched is ASSIGNEd ownMemo is ASSIGNEd D. h, die Propertys werden nicht gelöscht (?) oder zumindestens nicht Nil gesetzt. Wenn ich z. B. dann auf die procedure CreateOwnRichEd;virtual; procedure CreateOwnMemo;virtual; zugreife, gelten die propertys als assigned, und es wird .show angewendet. Allerdings zeigen sich die beiden nicht wieder, aber es wird auch kein Fehler ausgelöst. Woran liegt das - unterschiedliche Owner und Parent - Parent als Tform verhindert irgendwas? Bin gespannt Grüße Uwe |
AW: Freigeben vom Propertys aus Generics..Tlist<tcontrol> gelingt nicht
Hmm..
Dir ist (hoffe ich) wohl bekannt, das eine Variable, die auf ein Object 'zeigt' nicht auf 'nil' gesetzt wird, wenn das Object zerstört wird? ;) Sie behält die Adresse, wo das Object mal war! Dies ist bei jeder Objectvariable so... Egal ob dies ein ListItem oder direkt eine Variable ist. Bei einfachen Variablen gibt es dafür FreeAndNil()... |
AW: Freigeben vom Propertys aus Generics..Tlist<tcontrol> gelingt nicht
@HolgerX
Hallo, danke für die Antwort. hmm ... im Prinzip weiß ich daß, aber im Trial and Error habe ich gesehen, daß beim Löschen der Listen-Variablen im FUNKTIONIERENDEN BEISPIEL (Propertys direkt in tform gelegt) die Properties zum Schluß auch Nil waren:
Delphi-Quellcode:
ist FormRiched (oder FormMemo) hier schon NIL!
if assigned(list.items[0]) then
begin list.items[0].free; //freeandnil(list.items[0]) geht nicht Es wird hier FormRiched.free gerufen {list.items[0]:=nil;} //auch wenn ich den Listen-Eintrag nicht Nil setze end; ICH WEISS NICHT; WER DAS MACHT! Auch wenn ich den Listeneintrag NICHT Nil setze. Den Listeneintrag muß ich Nil setzen, um bei einer erneuten Listen-Nutzung dort dann nicht in einen nur scheinbar assigned Listeneintrag zu greifen. Im PROBLEMFALL wird ja ein ähnliches Konstrukt angewendet, nur das OwnRichEd und OwnMemo nicht das tForm als Eigentümer haben, sondern z.b. ein anderes Trichedit. Parent von den beiden Own-Komponenten wird erst gesetzt, damit sie sichbar werden im tForm. Beim Löschen über die Liste
Delphi-Quellcode:
wird zwar hier wohl z.B. Ownriched.free, damit Ownriched zerstört, aber eben nicht Nil gesetzt.
if assigned(TestRich_UA1.OwnControlList.items[0]) then
begin TestRich_UA1.OwnControlList.items[0].free; TestRich_UA1.OwnControlList.items[0]:=nil; end; Heißt für mich leider, daß es wohl nichts wird, aus einer Liste heraus Properties zu löschen (GEHT) und Nil zu setzen (GEHT NICHT). Die Hoffnung war, dies mit einer eleganten for-to-Schleife über die Listeneinträge zu schaffen statt z.B. so
Delphi-Quellcode:
hat sich da wohl erledigt.
case so of
ShowOwnRichEd_UA: if free then FreeAndNil(FOwnRichEd) else if assigned(ownriched) then ownriched.hide; ShowOwnMemo_UA: if free then FreeAndNil(FOwnMemo) else if assigned(OwnMemo)then OwnMemo.Hide; end; Und dennoch - warum geht das bei Properties auf der Form? Guß Uwe |
AW: Freigeben vom Propertys aus Generics..Tlist<tcontrol> gelingt nicht
Zitat:
Das funktioniert nur bei Feldern im published Bereich, so wie sie vom Form-Designer angelegt werden. Beim
Delphi-Quellcode:
wird
TComponent.Create
Delphi-Quellcode:
aufgerufen, was wiederum ein
AOwner.InsertComponent
Delphi-Quellcode:
aufruft. Darin wird im Owner nach einem (published) Field gesucht, daß den gleichen Namen hat wie die Komponente, und falls gefunden auf die Instanz der Komponente gesetzt. Nur durch diesen Mechanismus kann man die Form-Komponenten über ihren Variablennamen ansprechen.
SetReference(True)
Beim Destroy der
Delphi-Quellcode:
geht es dann den umgekehrten Weg über
TComponent
Delphi-Quellcode:
und
RemoveComponent
Delphi-Quellcode:
, was dann die Feld-Variable auf nil setzt.
SetReference(False)
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:02 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz