Announcement

Collapse
No announcement yet.

Austauschbare Frames in einer MainForm

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

  • Austauschbare Frames in einer MainForm

    Moin!

    Meine Applikation besteht aus einer MainForm und zwei Frames. Die MainForm beinhaltet ein Menü mit drei Punkten: „Exit“, „Frame1“ und „Frame2“. Jeder Frame beinhaltet jeweils einen Button. Die MainForm und die Frames sind in getrennten Projekten definiert. Die Frames sollen im Client-Bereich der MainForm angezeigt werden. Zum Wechseln zwischen den Frames benutze ich das Menü auf der MainForm. Nach einem Klick auf den Menü-Punkt „Frame1“ passiert folgendes:
    <PRE>procedure TForm1.MenueFrame1Click(Sender: TObject);
    begin
    if Assigned(LocalFrame)
    then LocalFrame.Destroy;

    LocalFrame := TFrame1.Create(self);
    LocalFrame.Parent := MainForm;
    LocalFrame.Show;
    end;</PRE>

    und nach einem Klick auf den Menü-Punkt „Frame2“ das:

    <PRE>procedure TForm1.MenueFrame2Click(Sender: TObject);
    begin
    if Assigned(LocalFrame)
    then LocalFrame.Destroy;

    LocalFrame := TFrame2.Create(self);
    LocalFrame.Parent := MainForm;
    LocalFrame.Show;
    end;</PRE>

    Wobei „LocalFrame“ eine Variable ist, die im Public Bereich der MainForm als TFrame definiert ist. Bis hier funktioniert alles sehr gut.

    Nun zu meinem Problem. Wie ich schon erwähnt habe, ist auf jedem Frame ein Button platziert. Nachdem Wechsel zwischen den Frames über das Menü so gut funktioniert hat, wollte ich auch die Buttons dazu verwenden. Und zwar so, dass ich im Frame1 (oder Frame2) stehend durch den Klick auf Button1 den Klick auf das Menü in der MainForm simuliere:

    <PRE>procedure TFrame1.Button1Click(Sender: TObject);
    begin
    MainForm.MainMenu1.Items[2].Click; //Items[2] -> Frame2
    end;

    procedure TFrame2.Button1Click(Sender: TObject);
    begin
    MainForm.MainMenu.Items[1].Click; //Items[1] -> Frame1
    end; </PRE>

    ... und das funktioniert nur teilweise richtig. Es wird zwar zwischen den Frames gewechselt, aber nach der Abarbeitung aller Anweisungen in TForm1.MenueFrame1Click (bzw. TForm1.MenueFrame2Click), kehrt das Programm in Procedure TFrame1.Button1Click (bzw. TFrame1.Button2Click) zurück. Doch dann wird eine Exception ausgelöst und das, wie ich meine zu Recht. Das Problem liegt daran das zwischen dem Zeitpunkt des Klicks auf den Button und dem Zeitpunkt des Rückers in TFrameX.Button1Click, wird der Frame gelöscht (LocalFrame.Destroy). Also anders gesagt der Button löscht den eigenen Frame („Sägt den Ast, auf dem er selber sitzt, ab) und das geht schief. Deswegen wird eine Exception ausgelöst.

    Wie kann ich den Fehler eliminieren?

    Viele Grüße
    Markus

  • #2
    Da gibt es zwei Möglichkeiten:

    1. den Wechsel nur von "aussen" anstossen (i.d.R. verwendet man - bei vielen Frames im selben Formular - ein TreeView, bei dem der Klick auf einen Eintrag rechts das Frame wechselt)

    2. Nutzung der Windows-Botschaftswarteschlange mittels PostMessage. Hierbei wird eine Message an das Formular gesendet und der Code wird ohne Warten auf die Abarbeitung der Message weitergeführ

    Comment


    • #3
      Moin Bruno!

      Vielen Dank für deine prompte Antwort.

      Zu 1.: ich glaube, das habe ich mit der Steuerung über das Menü realisiert. Sie liegt außerhalb aller Frames.

      Zu 2.: könntest Du mir ein Beispiel von solchen Funktion posten, da ich im Bereich der Windows-API Programmierung ein absoluter Anfänger bin? Kannst Du mir vielleicht ein Tipp geben womit man anfangen sollte, um in das Thema Windows-Api einzusteigen. Alles was ich bis jetzt gefunden habe (msdn.microsoft.com) ist für einen Anfänger ziemlich schwer.

      Viele Grüße
      Marku

      Comment


      • #4
        Hi Markus,<br>wenn ich das richtig kapiert habe, dann prüfe doch den Sender ab, ob es MainMenu ist, nur dann führst du den destroy des Frame aus...<br>
        Michae

        Comment


        • #5
          Hallo Marcus,<BR><BR>
          ich muss mich erst mal Bruno anschliessen. Eine Steuerung der View's sollte nur von außen an einer zentralen Stelle erfolgen. Die Frames sollten MainForm gar nicht kennen.<BR>
          Übrigens kommt bei mir (Delphi 7) keine Exception. Vielleicht reicht es ja schon, statt LocalFrame.Destoy LocalFrame.Free aufzurufen (Destroy sollte man nie direkt aufrufen) und asl erstes noch mal Application.ProcessMessages (vor dem Free).
          <PRE>
          Application.ProcessMessages;
          if Assigned(LocalFrame) then
          begin
          LocalFrame.Free;
          LocalFrame := nil;
          end;
          LocalFrame := TFrame2.Create(self);
          LocalFrame.Parent := pnlCont;
          LocalFrame.Show;
          </PRE>

          Aber den Code bezeichnet man dann als Spaghetti - Code, da alles miteinander verwunden ist.<BR>
          Wenn du die Erzeugung der Frames auch aus den Frames steuern willst, so musst du eine eigene Unit mit einer eigenen Klasse (TFrameManager) oder so schreiben. Dieser erhält eine Public Method ShowNewFrame, und sowohl das MainForm als auch die Frames kennen nur den FrameManager und rufen seine Methoden auf.<BR>
          Gruß, Fran

          Comment


          • #6
            Ach ja, wenn du mit Assigned prüfst, musst du auch die Var nach Zerstörung des Objektes auf nil setzen, denn Destroy oder Free ändern nicht deine Variable. Das scheint zwar hier nicht nötig zu sein, da du diese ja sofort neu belegst. Aber wenn im Constructor deines Frames mal eine Exception auftritt, so wird LocalFrame halt nicht neu belegt und verweist dann auf ein bereits zerstörtes Object. Beim nächsten Versuch, dieses zu zerstören, kommt mit Sicherheit eine Exception.<BR>
            Fran

            Comment

            Working...
            X