Einzelnen Beitrag anzeigen

Delbor

Registriert seit: 8. Okt 2006
Ort: St.Gallen/Schweiz
1.186 Beiträge
 
Delphi 11 Alexandria
 
#15

AW: Seltsames Verhalten der Destruktoren

  Alt 13. Dez 2017, 08:11
Hi Ghostwalker

Dir auch einen guten Morgen!

Zitat:
Beim schließen des Dokumentes passiert nun folgendes:
Frame2.Destructor räumt sich auf und gibt das Handel vom Dokument frei.

danach

Frame1.Destructor räumt sich auf und versucht das Handel des Dokumentes frei zu geben.
Da Frame2 das schon gemacht hat, gibts eine AV.
Sorry, wenn ich dir widerspreche! Bau dir doch mal ein kleines Testprogramm, ohne jede Komponente. Wenn du nun in der Toolleiste unter 'Standard<=Frames' dieses anklickst, dann auf die Form dahin klickst, wo du denn Frame haben willst, geschieht - nichts. Da zu dem Projekt noch kein Frame existiert, gibts auch keine Liste mit zur Verfügung steheden Frames, die dir angezeigt werden könnte.
Abhilfe schaffen 2 Möglichkeiten:
  • Du hast einen Frame, den du gerne in dem Projekt verwenden möchtest, der aber in einem völlig anderen Ordner liegen hast.
    • Öffne diesen Frame und speichere ihn unter dem gleichen Namen(wichtig!!!). aber natürlich nur den Dateinamen, in deinem Projektverzeichnis.
    • Dann klickst du auf <Projekt =>> Dem Projekt> hinzufügen und wählst nun die *.pas des Frames, um sie hinzuzufügen.
    • Nun kannst du ihn in der Toolpalette unter Frames auch auswählen.
  • Alternativ dazu kannst du unter >Datei =>> Neu =>> weitere> als neu zu erstellendes Objekt einen Frame wählen und erhälst nun einn leeres Feld, ähnlich wie bei einer Form
  • Diesen speicherst du wiederum im Projektorder. Dem Projekt hinzufügen musst du diesmal nicht - das hat Delphi schon gemacht

Nun hast du dem Projekt einen Basisframe hinzugefügt. Auf der Form hingegen befindet sich noch keine Frameinstanz. Nun setze im Projektverzeichnis einen Haltepunkt auf die Mainform - der soeben hinzugefügte Frame ist zwar in der uses-Liste vorhanden, nicht aber zwischen begin/end.
Wenn du nun das Projekt startest, wirst du bemerken, dass vor dem Erzeugen der Mainform der Basisframe erzeugt wird. Zumindest, wenn du diesem einen construktor himzugefügt hast und mit F7 durchstepst.
Bei Programmende laufen die Prozeduren in umgekehrter Reihenfolgee ab. Erst wird also die Form (mit ihren allfälligen Frameinstanzen) freigegeben und erst dann der Basisframe. Zusammen mit den Frameinstanzen werden auch deren Komponenten, Klassen und Handles freigegeben - _Document ist letzteres. Das _Document des Basisframes wird also erst mit diesem freigegeben (bzw. sollte vor dessen Zerstörung freigegeben werden. Aber da bin ich mir nicht sicher).

Vererbung erfolgt immer vom Basisframe zur Frameinstanz, umgekehrt jedoch nicht (wie das in Delphi überall der Fall ist). Wenn die Frameinstanzen der Form zerstört werden, werden also auch allfällige Handles dieser Instanzen zerstört, nicht aber das im Basisframe enthaltene Handle - das verzieht sich erst mit dem Basisframe ins Nirwana.

Wenn nun das Dokument 7 Seiten enthält und ich mir, wie oben ausgeführt, von der Prozedur GetPageAT eine Seite zurückgeben lasse, existieren erstmal acht Seiten. - zumindest in einer (oder auch beiden) Frameinstanzen. Dies wird in der Prozedur LoadVisiblePages bereinigt, wo alle nicht sichtbaren Seiten freigegeben werden. Anbei ein Ausschnitt aus PaintWindow:
Delphi-Quellcode:
// check visibility
  if FReload or (FPages.Count = 0) then
  begin
    LoadVisiblePages;
    PDFiumFramePaintWindowToMemo1;
    FReload := False;
  end;
FReload muss hier also true sein, dass LoadVisiblePages aufgerufen wird.
So, wie ich den Programmablauf bisher verstanden habe, wird also ohne Aufraufe von PaintWindow und LoadVisiblePages und dem setzen von FReload auf True gar nichts neu gezeichnet, und es werden auch keine nichtsichtbaren Fenster gelöscht - auch deren Handles nicht.
Ich habe bislang noch nie mit Handles direkt gearbeitet, aber ich würde mich wohl schwer irren, wenn Windows ein Handle löschen (lassen) würde, das noch selbst ein gültiges Handle besitzt.

Ich weiss nicht, ob ich nun alles richtig verstanden habe, aber - weitermachen zeigt, was Sache ist.

Gruss
Delbor

PS:
Zitat:
Sinnvoller wäre es, das Dokument in der Form zu erzeugen und wieder frei zu geben und das ganze dann an die Frames zu übergeben.
Nein, in diesem Fall nicht. TPDFiumFrame ist in sich selbst voll funktionstüchtig. Zusammen mit der mitgelieferten Unit PDFium.Wrapper; gehörte er zu einem Beispielprojekt. Ich habe ihn hier in diese Anwendung auf die oben beschriebenen Weise importiert und die Wrapper-Unit unter diesem Projekt abgespeichert und hinzugefügt. Mehr braucht es - ausser der PDFium.dll - nicht, um PDF-Dokumente anzeigen und darin hin-und her scrollen zu können. Würde ich die Erzeugung des Dokumentes in die Form verlegen, müsste ich auch den ganzen Code des Basisframes in die Formunit verlegen - und das sind doch unter Berücksichtigung der Kommentare und meiner Report- und Memo-Ausgaben knappe tausend Zeilen. (Aktuell, mit allen meinen Änderungen: 1051)
Roger
Man muss und kann nicht alles wissen - man muss nur wissen, wo es steht.
Frei nach Albert Einstein
http://roase.ch

Geändert von Delbor (13. Dez 2017 um 08:42 Uhr)
  Mit Zitat antworten Zitat