Announcement

Collapse
No announcement yet.

Problem beim Erzeugen von Fenstern

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Problem beim Erzeugen von Fenstern

    Hallo zusammen,

    folgende Situation: 3 Formulare, FMain, F1 und F2. F1 und F2 sollen nur bei Bedarf erzeugt werden, d.h sie werden nicht beim Start automatisch erzeugt.
    F1 und F2 sollen Modal erzeugt werden, sobald im Hauptmenü in FMain auf den entsprechenden Eintrag geklickt wird:

    [pre]
    procedure MenueClick1(Sender:TObject);
    begin
    F1:=TF1.Create(Application);
    F1.ShowModal;
    F1.Release;
    end;
    [/pre]

    Deklaration F1 (analog dazu F2!):

    [pre]
    type
    TF1 = class(TForm)
    Panel1: TPanel;
    .
    .//irgendwelche KOmponenten, Prozeduren und Funktionen
    .
    procedure GridBrowse;
    end;

    var
    F1: TF1;
    implementation
    [/pre]

    Das klappt auch alles einwandfrei. Nun soll auch aus F1 das Fenster F2 aufgerufen werden. Also in die Uses-Clause kommt dann die Unit UF2, und in die OnClick-Prozedur folgender Code:

    [pre]
    procedure buttonOnClick(Sender:TObject);
    var frm:TF2;
    begin
    frm:=TF2.Create(ApplicatioN);
    frm.ShowModal;
    frm.Release;
    end;
    [/pre]

    Wenn ich das Proggy so starte kommt es beim Aufruf von F2 aus F1 irgendwann zu einem EAccessViolation. Rufe ich das Fenster F2 von FMain auf, klappt alles einwandfrei!

    Nun der große Trick: ändere ich den Aufruf von F2 aus F1 folgendermaßen ab:

    [pre]
    procedure buttonOnClick(Sender:TObject);
    begin
    F2:=TF2.Create(ApplicatioN); //die Variable F2 wird ja in der Unit UF2 deklariert!
    F2.ShowModal;
    F2.Release;
    end;
    [/pre]

    Klappt auch der Aufruf aus F1 heraus OHNE den Zugriffsfehler. Warum denn?!?! Ich ändere doch lediglich den Namen einer Variable! Hab ich vielleicht was grunsätzliches noch nicht kapiert???

    Grüße und vielen Dank für Hinweise und ein schönes WE wünscht
    Wolfgang Lemmermeyer

  • #2
    Hallo Wolfgang,<p>
    mit Verlaub, ich glaube du hast tatsächlich etwas Grundsätzliches nicht kapiert.<p>
    F2 und fmr sind Variablen vom Typ TF2. Sie sind allerdings Objekt-Referenzen. Eine Objektreferenz ist im Prinzip auch nichts anderes als ein Zeiger auf ein Objekt. Der Unterschied zum Zeiger ist, daß man beim Dereferenzieren von der Syntax her nicht erkennen kann, daß man mit einem Zeiger arbeitet und man kann auch keine Zeigerarithmetik damit betreiben. Man kann eine Objektreferenz aber jederzeit auf ein anderes Objekt ausrichten.<br>
    Nun was machst du. In der Unit UF2 wird eine globale Variable F2 definiert. In deinem Hauptformular erzeugst du ein Objekt vom Typ TF2 und richtest die Objektreferenz F2 auf dieses Objekt aus. Das ist korrekt.<br>
    Von deinem Formular F1 aus definierst du eine Variable namens frm innerhalb der Methode buttonOnClick(Sender:TObject). Dann erzeugst du ein Objekt vom Typ TF2 und richtest die lokale Objektreferenz frm auf dieses Objekt aus. Innerhalb der Methode kannst über frm völlig korrekt das Objekt ansprechen. frm exisistiert allerdings nur während der Ausführung der Methode. Sobald die Methode beendet wird, verlierst du den Zugang zu deinem Formular-Objekt, das sehr wohl weiter lebt.<br>
    Über die Objektreferenz F2, die global ist und somit zur Laufzeit des Programms exisiert, kannst du dieses Formular nicht ansprechen. Wenn du nämlich nach dem Programmstart so vorgehst, daß du Formular F1 öffnest und danach von F1 aus das Formular F2 erzeugst, dann zeigt deine Objektreferenz F2 noch ins Nirwana und jeder Zugriff über F2 auf das Formular F2 führt dann unweigerlich zu einer EAccessViolation.<br>
    Dein Trick, wie du es nennst, ist nichts anderes als die korrekte Vorgehensweise.<p>
    Keine Ahnung, ob ich mich jetzt verständlich ausgedrückt habe, falls nicht, frag einfach nach.<p>
    Gruß<p>
    Wolfgang Rolle

    Comment


    • #3
      Hallo Wolfgang,

      erst mal Danke für Deine Hilfe! Die Bedeutung der Begriffe Objektreferenz und Zeiger sind mir geläuftig.
      <b>
      Von deinem Formular F1 aus definierst du eine Variable namens frm innerhalb der Methode buttonOnClick(Sender:TObject). Dann erzeugst du ein Objekt vom Typ TF2 und richtest die lokale Objektreferenz frm auf dieses Objekt aus. Innerhalb der Methode kannst über frm völlig korrekt das Objekt ansprechen. frm exisistiert allerdings nur während der Ausführung der Methode. Sobald die Methode beendet wird, verlierst du den Zugang zu deinem Formular-Objekt, das sehr wohl weiter lebt.
      </b>

      Klar kann ich nur auf frm zugreifen solange ich in der OnClick-Proc bin. Habe ich auch nicht anders gemacht. Aber weshalb lebt das Formularobjekt weiter, nachdem ich es mit .release freigegeben habe???

      Nochmal mein Problem besteht darin, daß ich über kurz oder lang bei folgendem Aufruf
      <pre>
      procedure buttonOnClick(Sender:TObject);
      var frm:TF2;
      begin
      frm:=TF2.Create(ApplicatioN);
      frm.ShowModal;
      frm.Release;
      end;
      </pre>
      eine Zugriffsverletzung bekomme wenn ich mich in der Form (also TF2, nach aufruf durch ShowModal) bewege.

      Mit Deiner Erklärung passt doch dann alles: Ich deklariere eine Variable (frm) vom Typ TF2. Anschließend erzeuge ich das Objekt (frm:=TF2.Create), lasse das Fenster mit ShowModal anzeigen und kann darin rumwerkeln. Aber genau dann passiert es, daß ich hin und wieder die Zugriffsverletzung bekomme. Ich greife nicht mit F2.Irgendwas auf Komponenten oder Funktionen zu. Die Ausführung bleibt ja an der Stelle (ShowModal) stehen und es wird damit nur noch Code aus der Untit UF2 ausgeführt. Und dort steht "normaler" Code, also nix, was irgendwie die Variable F2.*** benötigt.

      Grüße
      WOlfgan

      Comment


      • #4
        Hallo Wolfgang,<p>
        du hast natürlich Recht. Das Formular existiert nicht über die Laufzeit der Methode procedure buttonOnClick(Sender:TObject); hinaus. Ich habe das frm.Release einfach überlesen.<br> Was vielleicht daran liegt, daß ich es noch nie verwendet habe. Ich setze bei meinen Formularen im OnClose-Ereignis Action := caFree; und rufe dann immer Close auf.<p>
        Das löst natürlich dein Problem nicht. So gesehen bin auch ratlos und würde sagen, müßte eigentlich funktionieren. Kannst du nicht mit Hilfe des Debuggers die Stellen identifizieren, die die EAccessViolation auslösen?<p>
        Gruß<p>
        Wolfgang Rolle

        Comment


        • #5
          Hi,

          das mit dem Debugger habe ich auch versucht, doch da erhalte ich bei zwei Durchläufen garantiert 2 unterschiedliche Stellen bzw. beim ersten Aufruf der Funktion klappts, beim zweiten mal nicht mehr. Ich versuche mal einen Fall aus meinem Gedächtnis zu rekonstruieren:

          Beim Start (OnShow) wird eine Procedure aufgerufen, die kontrolliert welche Seite einer TPageControl aktiv ist, bzw. eine bestimmte Seite setzt. Beim ersten Aufruf klappt alles einwandfrei, beim zweiten mal ist die Variable der Komponente (also pctrlAuftrag) nicht mehr definiert (zeigt im Debugger nil an). Ich kann es mir einfach nicht erklären aber wichtig ist, daß ich mit meinem Wissen doch nicht daneben liege.

          Grüße
          Wolfgan

          Comment

          Working...
          X