AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Das verrückte Formular

Ein Thema von Tenobaal · begonnen am 21. Aug 2014 · letzter Beitrag vom 21. Aug 2014
Antwort Antwort
Tenobaal

Registriert seit: 9. Mai 2013
21 Beiträge
 
Delphi XE5 Professional
 
#1

Das verrückte Formular

  Alt 21. Aug 2014, 11:08
Hallo! Ich möchte ein Formular im Clientbereich einer TPanel-Komponente einblenden. Soweit kein Problem, habe ich schon tausend mal gemacht. Es funktioniert auch, allerdings verhält sich das Formular im Clientbereich des Panels dann nicht wie erwartet. Wenn ich das Formular im eigenständigen Fenster erzeuge, funktioniert es jedoch wie es soll.

Ich gebe mal einen kurzen Überblick über den Quellcode des Projekts, den ich auf das wesentliche reduziert habe:

Formular TForm1
  • Hauptformular zur Demonstration des Programms.
  • Hat eine TPanel Komponente auf dessen Clientbereich das Formular "TFormCreateGeometry" eingeblendet werden soll, wenn der Button "Erzeuge im Panel" gedrückt wird.
  • Der Button "Erzeuge im Fenster" erzeugt das Formular "TFormCreateGeometry" als eigenständiges Fenster.

Formular TFormCreateGeometry
  • Das Formular "TFormCreateGeometry" enthält eine TTreeView Komponente. Im OnCreate-Event des Formulars werden die 5 Knoten Rootnode, LinesNode, PointsNode, AreasNode, MatNode erstellt und dem TreeView hinzugefügt.
  • Der Button "btnAddPoints" soll dem Knoten "PointsNode" zur Laufzeit des Programms weitere Kindknoten hinzufügen.

Problembeschreibung:
Wird das Formular "TFormCreateGeometry" im Clientbereich des Panels erstellt, dann werden die Kindknoten nach betätigen des Buttons "btnAddPoints" nicht dem Knoten "PointsNode" sondern dem Knoten "LinesNode" hinzugefügt.
Wenn das Formular "ganz normal" im eigenständigen Fenster erstellt wird, dann werden die Kindknoten wie erwartet dem Knoten "PointsNode" angehangen.
Ich suche schon seit zwei Tagen nach dem Fehler und bin keinen Schritt weiter gekommen. Ich habe auch schon ein neues Projekt angelegt, um auszuschließen das die Entwicklungsumgebung (RAD Studio XE5) etwas an den Dateien manipuliert hat, was im Quellcode nicht sichtbar ist.
Angehängte Dateien
Dateityp: zip Projekt.zip (57,8 KB, 11x aufgerufen)

Geändert von Tenobaal (21. Aug 2014 um 11:24 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.648 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: Das verrückte Formular

  Alt 21. Aug 2014, 11:42
Erklären kann ich das auch nicht ohne genauer zu debuggen, aber es wird wohl daran liegen, dass das Formular so ein zweites Mal angezeigt wird und dabei evtl. irgendwelche Handles neu erzeugt werden. Dadurch zeigen dann die Knoten auf den falschen Zielknoten wie du beim Debuggen sehen kannst (einfach Maus über PointsNode halten, wenn du in der Zeile bist, in der die Punkte hinzugefügt werden).

Aufgrund solcher und anderer Probleme, insbesondere was die Langsamkeit und die fehlende Anpassbarkeit angeht, nutze ich auch ausschließlich die Virtual Trees.

Nichtsdestotrotz ist es ohnehin keine gute Idee im Konstruktor mehr zu machen als Klassen zu erzeugen usw., so dass die funktionierende Lösung im Anhang ohnehin die sauberere Lösung ist. Und zwar einfach eine separate Methode zur Initialisierung benutzen.
Angehängte Dateien
Dateityp: 7z Projekt_new.7z (54,3 KB, 1x aufgerufen)
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
Dejan Vu
(Gast)

n/a Beiträge
 
#3

AW: Das verrückte Formular

  Alt 21. Aug 2014, 11:43
-Blödsinn-
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.475 Beiträge
 
Delphi 12 Athens
 
#4

AW: Das verrückte Formular

  Alt 21. Aug 2014, 12:00
Duch das Setzen von Form.Parent := pnl1; wird ein DestroyHandle aufgerufen, was intern dazu führt, daß die Items des TreeView freigegeben und neu erzeugt werden. Dadurch werden die gespeicherten Pointer auf die TreeNodes ungültig.

Eventuell kannst du das Anlegen der Nodes in eine separate Methode verlagern, die du nach dem Setzen des Parent nochmal aufrufst.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#5

AW: Das verrückte Formular

  Alt 21. Aug 2014, 12:05
Duch das Setzen von Form.Parent := pnl1; wird ein DestroyHandle aufgerufen, was intern dazu führt, daß die Items des TreeView freigegeben und neu erzeugt werden. Dadurch werden die gespeicherten Pointer auf die TreeNodes ungültig.
Es kommt immer darauf an, wie das intern behandelt wird.

Wenn nur die Handles freigegeben werden, dann bleiben meistens dennoch die TObjekt-Klassen erhalten und danach wird dann daraus/darin dann wieder das neue Handle erzeugt.
Aber wie der TreeView intern mit seinen Items umgeht, weiß ich jetzt auch nicht.

Das kann man aber leicht prüfen.
> Einfach vor dem AddChild nochmal den "aktuellen" Wert auslesen, also das Item suchen, und dann die Zeiger vergleichen.

Natürlich kann man auch einfach immer den Parent jedesmal über den Namen neu suchen, beim Add, und auf diese globalen Variablen verzichten, vorallem wenn mann jetzt weiß (vermutlich), daß es mit diesen Zeigern gern Probleme gibt und sie sich schnell mal ändern könnten.
$2B or not $2B
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.475 Beiträge
 
Delphi 12 Athens
 
#6

AW: Das verrückte Formular

  Alt 21. Aug 2014, 12:18
Duch das Setzen von Form.Parent := pnl1; wird ein DestroyHandle aufgerufen, was intern dazu führt, daß die Items des TreeView freigegeben und neu erzeugt werden. Dadurch werden die gespeicherten Pointer auf die TreeNodes ungültig.
Es kommt immer darauf an, wie das intern behandelt wird.
In TCustomTreeView.DestroyWnd wird der Inhalt von Items in einen MemoryStream geschrieben und Items.Clear aufgerufen. In dem Moment sind die TreeNode-Pointer schon ungültig, obwohl sie noch die richtigen Daten enthalten. Nach dem Recreate werden die TTreeNodes zwar wieder hergestellt, allerdings stimmt die Position im Speicher mit hoher Wahrscheinlichkeit nicht mehr mit der vorigen überein. Das dauerhafte Speichern von Pointern auf TreeNodes ist also mit Vorsicht zu genießen. Leider gibt es auch keinen brauchbaren Event, mit dem man das abfangen könnte.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#7

AW: Das verrückte Formular

  Alt 21. Aug 2014, 12:20
PS: Wenn sich die Zeiger geändert haben, dann ist es doch ein großer Zufall, daß die neue Instanz zufällig auf der Adresse der alten Instanz des anderen Knoten liegt.


brauchbarer Event: TreeView ableiten, die "CreateWnd"-Methode überschreiben und sein eigenes Event implementieren,
bzw. die Methode, welche den Nodes aus'm Stream läd.
$2B or not $2B

Geändert von himitsu (21. Aug 2014 um 12:22 Uhr)
  Mit Zitat antworten Zitat
Tenobaal

Registriert seit: 9. Mai 2013
21 Beiträge
 
Delphi XE5 Professional
 
#8

AW: Das verrückte Formular

  Alt 21. Aug 2014, 12:25
Duch das Setzen von Form.Parent := pnl1; wird ein DestroyHandle aufgerufen, was intern dazu führt, daß die Items des TreeView freigegeben und neu erzeugt werden. Dadurch werden die gespeicherten Pointer auf die TreeNodes ungültig.

Eventuell kannst du das Anlegen der Nodes in eine separate Methode verlagern, die du nach dem Setzen des Parent nochmal aufrufst.
Mir war nicht bewusst, dass Form.Parent := pnl1; ein DestroyHandle aufruft. Beim Debuggen fiel mir auch auf, dass die zuvor angelegten TTreeNode-Objekte (Rootnode, LinesNode... etc.) falsche Objektadressen haben, nachdem das neue Parent gesetzt wurde. Das scheint eine Eigenart beim TreeView sein, denn bisher ist ein derartiges Problem noch nicht aufgetreten, obwohl ich ständig Formulare auf irgentwelche Panel setze.

Tausend Dank für eure Hilfe

Geändert von Tenobaal (21. Aug 2014 um 12:27 Uhr)
  Mit Zitat antworten Zitat
pertzschc

Registriert seit: 29. Jul 2005
Ort: Leipzig
309 Beiträge
 
Delphi 12 Athens
 
#9

AW: Das verrückte Formular

  Alt 21. Aug 2014, 12:47
???
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#10

AW: Das verrückte Formular

  Alt 21. Aug 2014, 12:50
Gut, daß die Objektinstanzen bei sowas verschwinden, ist auch recht selten und passiert bei den meisten VCL-Klassen auch nicht.

Das dahinterliegende Windows-Handle kann aber schnell mal verschwinden und neu entstehen,
wobei dann gerne Dinge verloren gehn, die man im OnCreate oder im Contructor eingestellt hat, indem man die WinAPI nahm und es direkt im Handle erledigte.
(Drag&Drop aktivieren, EM_SETCUEBANNER, usw.)

Er hat seinen Beitrag schnell genug editiert, so daß die DP noch keine "editiert"-Meldung drunterschreibt.
Und das gelöscht, was vorher drin stand, welches er als unpassende/falsche Antwort empfand.
$2B or not $2B

Geändert von himitsu (21. Aug 2014 um 12:55 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:14 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz