Autor Beitrag
Peter18
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Mo 13.06.16 13:57 
Ein freundliches Hallo an alle,

ich habe ein StringGrid von TStringGrid abgeleitet und ihm ein Kontextmenu spendiert, über das Zeilen und Spalten eingefügt und gelöscht und auch Zellinhalte in die Zwischenablage kopiert werden können.

Meine Frage: Wenn mehrere solcher Grids in einem Programm verwendet werden und eines der Grids wird freigegeben, wie ist es dann im Destructor zu handhaben? Beim ersten Versuch habe ich "PopupMenu.Free" und "oClipboard.Free" eingetragen, weil sie im Constructor erzeugt werden und einen Laufzeitfehler erhalten.

Dabei hat "PopupMenu.Free" schon beim ersten Grid zu einem Fehler geführt und "oClipboard.Free" erst beim zweiten.
Da ich das Menü mit "PopupMenu := TPopupMenu.Create ( Self );" direkt zugewiesen habe wird es vielleicht von "TDrawGrid" freigegeben.

Bisher handhabe ich es so, dass Objekte, die ich selbst erzeuge, auch von mir freigegeben werden. Gibt es da noch andere Regeln??

Grüße von der verregneten Nordsee

Peter
Nersgatt
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 1581
Erhaltene Danke: 279


Delphi 10 Seattle Prof.
BeitragVerfasst: Mo 13.06.16 14:03 
user profile iconPeter18 hat folgendes geschrieben Zum zitierten Posting springen:
Da ich das Menü mit "PopupMenu := TPopupMenu.Create ( Self );

Du übergibst ja self als owner. Damit wird das Popupmenu automatisch freigeben, wenn Du das Grid freigibst (bzw. es freigegeben wird).
Wenn Du es selbst freigeben möchtest, dann erzeuge es lieber mit PopupMenu := TPopupMenu.Create (nil)

_________________
Gruß, Jens
Zuerst ignorieren sie dich, dann lachen sie über dich, dann bekämpfen sie dich und dann gewinnst du. (Mahatma Gandhi)
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Mo 13.06.16 15:31 
Hallo Jens,

Dank Dir für Deine Antwort. Ich möchte verstehen, was da geschieht. Mit "Self" wird das Popupmenu also in der Objektliste eingetragen und automatisch freigegeben? Gilt das nur für die beendete Instanz vom Stringgrid oder für alle? Werden die Objekte der Liste freigegeben, bevor der Destructor aufgerufen wird?

Wenn das automatisch geschieht ist es ja in Ordnung.

Grüße von der micht mehr verregneten Nordsee

Peter
mandras
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 429
Erhaltene Danke: 107

Win 10
Delphi 6 Prof, Delphi 10.4 Prof
BeitragVerfasst: Di 14.06.16 00:17 
Durch das self wird das Menü in der Liste untergeordneter Elemente des Grids eingetragen und somit
automatisch beim Destruct des Grids freigegeben.

Wo der Fehler auftritt hängt von der Realisierung Deines Destructors ab:
Wenn Du vor dem "inherited" das Menü freigibst wird in der VCL ein Fehler auftreten weil
das originäre Grid nochmal das Menü freigeben will.

Gibst Du das Menü nach dem Inherited im Destructor frei erfolgt die Fehlermeldung bei Deinem .free

Du must Dich also entscheiden ob Du
1) Im Konstruktor als Parent "nil" angibst und im Destructor dann selbst das Menü freigibst
2) oder als Parent "self" angibst und im Destruktor nichts tust weil das Grid als Nachfahr von TControl alles übernimmt.

Grüße von der verregneten Ems :)

PS - Interna:

Wenn Du dem Konstruktor einer Component einen nicht-Nil-Wert übergibst ruft der intern immer das InsertComponent der so übergebenen übergeordneten Komponente auf: (Auszug aus der VCL)

constructor TComponent.Create(AOwner: TComponent);
begin
FComponentStyle := [csInheritable];
if AOwner <> nil then AOwner.InsertComponent(Self);
end;
baumina
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 305
Erhaltene Danke: 61

Win 7
Delphi 10.2 Tokyo Enterprise
BeitragVerfasst: Di 14.06.16 08:01 
Alles was du in einer Klasse erzeugst und freigibst, gilt immer nur für eine Instanz, alle anderen Instanzen bleiben davon unbetroffen.
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Di 14.06.16 11:19 
Hallo mandras, hallo baumina,

Dank Euch für Eure Antworten. Prinzipiell rufe ich im Constructor zuerst "inherited" auf und erzeuge dann alle anderen Objekte. Beim Destructor rufe ich "inherited" als letztes auf. Beim StringGrid führt das jedoch zu einem Fehler. Da schwimm ich auch noch.

Objekte mit Parent werden also automatisch freigegeben, alle anderen muß ich selbst beseitigen?

baumina, so hatte ich das auch erwartet, aber ich erzeuge mehrere StringGrids. Beim Ersten geht "oClipboard.Free" klar, aber bei den folgenden tritt ein Fehler auf. Mit "if Assigned( oClipboard ) then oClipboard.Free;" umgehe ich diesen Fehler. Das verstehe ich nicht.

Grüße von der trüben aber trockenen Nordsee (Die See ist natürlich nicht trocken :wink: )

Peter
Nersgatt
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 1581
Erhaltene Danke: 279


Delphi 10 Seattle Prof.
BeitragVerfasst: Di 14.06.16 11:23 
Hast Du von oClipboard denn für jede Instanz von den Stringgrids auch eine eigene Instanz? Zeigt oClipboard an der Stelle auch wirklich auf die Instanz, die zur Stringrid-Instanz gehört?
Ich denke, Du wirst mal ein bisschen Code zeigen müssen, um das rauszufinden.

_________________
Gruß, Jens
Zuerst ignorieren sie dich, dann lachen sie über dich, dann bekämpfen sie dich und dann gewinnst du. (Mahatma Gandhi)
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Di 14.06.16 13:30 
Hallo Jens

nochmals Dank.

Im Constructor steht
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
constructor T_StrGrid.Create( PW : TComponent );
begin
  inherited Create( PW );
......
  oClipboard := Clipboard;
end;


Falls das nicht genügt, sag mir, was Du brauchst.

Grüße von der etwas helleren Nordsee

Peter
baumina
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 305
Erhaltene Danke: 61

Win 7
Delphi 10.2 Tokyo Enterprise
BeitragVerfasst: Di 14.06.16 13:32 
Wahrscheinlich ist deine Instanz oClipboard vom Typ TClipboard, welches wiederum die Windows-Zwischenablage widerspiegelt und einer Sonderbehandlung bedarf, hier ein Auszug aus der Hilfe:

Zitat:
TClipboard repräsentiert die System-Zwischenablage.

TClipboard ist ein Container für die System-Zwischenablage, die alle Informationen, die in einer Anwendung ausgeschnitten oder kopiert wurden, enthält.

Instantiieren Sie einzelne TClipboard-Objekte nicht durch einen Aufruf des Kontruktors, sondern verwenden Sie die globale Instanz von TClipboard, die von der Funktion Clipboard zurückgegeben wird. Durch den Einsatz dieser globalen Instanz kann die Anwendung eine einzelne Instanz von TClipboard für alle Zwischenablagenoperationen verwenden, und ein unbeabsichtigtes Löschen der Zwischenablage wird ausgeschlossen.

Nersgatt
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 1581
Erhaltene Danke: 279


Delphi 10 Seattle Prof.
BeitragVerfasst: Di 14.06.16 13:38 
Das Clipboardobjekt ist ein Sonderfall. Das ist eine Instanz von TClipboard und davon soll nur eine Instanz existieren (das nennt man Singleton). (*)
Nun kopierst Du praktisch den Zeiger von Clipboard nach oClipboard (jetzt zeigen beide Variablen auf die selbe Instanz!!). Wenn Du nun oClipboard.Free aufrufst, ist diese eine Instanz freigeben.

Du solltest auf oClipboard komplett verzichten und direkt Clipboard benutzen (in allen Instanzen von Deinen Stringgrid). Um die Freigabe von Clipboard musst Du Dich in diesem Fall nicht kümmern. Das wird im finalization-Abschnitt der Unit Clipbrd erledigt.

(*) eigentlich ist Clipboard eine Function, die eine Instanz von Clipboard zurückliefert, aber das tut hier nichts zur Sache.

_________________
Gruß, Jens
Zuerst ignorieren sie dich, dann lachen sie über dich, dann bekämpfen sie dich und dann gewinnst du. (Mahatma Gandhi)
Peter18 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 489
Erhaltene Danke: 2


Delphi4
BeitragVerfasst: Di 14.06.16 15:14 
Hallo Baumina, hallo Jens,

nochmals Dank! Das heißt also "oClipboard.Free" ist überflüssig und ich kann auch "Clipboard.AsText := 'Text';" schreiben?

Grüße von der Nordsee

Peter
Nersgatt
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 1581
Erhaltene Danke: 279


Delphi 10 Seattle Prof.
BeitragVerfasst: Di 14.06.16 17:03 
user profile iconPeter18 hat folgendes geschrieben Zum zitierten Posting springen:
nochmals Dank! Das heißt also "oClipboard.Free" ist überflüssig und ich kann auch "Clipboard.AsText := 'Text';" schreiben?

Jepp!

_________________
Gruß, Jens
Zuerst ignorieren sie dich, dann lachen sie über dich, dann bekämpfen sie dich und dann gewinnst du. (Mahatma Gandhi)