Announcement

Collapse
No announcement yet.

D7 - showmodal brauche ich nur fensterspezifisch

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

  • D7 - showmodal brauche ich nur fensterspezifisch

    Ich meiner Applikation können die Anwender aus einem Hauptprogramm heraus eine beliebige Anzahl von Unterprogrammen starten (z.B. Adressverwaltung, Lager, ...).
    Die Fenster starte ich dynamisch per:
    Procedure Mainform.Adressenclick(Sender:Tobject);
    var f : TForm_AAW_BelegEdit;
    begin
    inherited;
    f:=TForm_AAW_BelegEdit.Create(self);
    try
    f.Show;
    finally
    end;
    end;
    Das gestartete Form sorgt für die "Eigenvernichtung" im Close-Event per "action:=caFree".
    Das funktioniert soweit wunderbar.

    Jetzt brauche ich allerdings folgendes:
    Aus der Adressverwaltung wird z.B. eine Suchfunktion (=neues Fenster) gestartet. Wie zeige ich dieses Fenster am besten an?
    Verwende ich
    f.show -> hat der Anwender leider immer noch Zugriff auf das aufrufende Fenster (also in diesem Beispiel auf die Adressfunktion)
    f.showmodal -> dann ist meine Suchfunktion leider das einzige Fenster, das der Anwender in meinem Programm überhaupt noch erreichen kann. Parallel gestartete weitere Unterprogramm (z.B. weitere Adressverwaltungen oder Lagerprogramme) sind dann leider solange nicht nutzbar, bis das modale Fenster geschlossen wird.
    Gibt's da eine Möglichkeit?

  • #2
    Hi motions,
    in folgendem Beispiel wird das Form solange disabled, bis das andere Form geschlossen wird.
    <CODE>
    unit Unit1;<BR>
    interface<BR>
    uses
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
    Dialogs, StdCtrls;<BR>
    type
    TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    private
    FModalView: TForm;
    { Private-Deklarationen }
    protected
    procedure Notification(AComponent: TComponent; Operation: TOperation); override;
    public
    { Public-Deklarationen }
    end;<BR>
    var
    Form1: TForm1;<BR>
    implementation<BR>
    uses Unit2;<BR>
    {$R *.dfm}<BR>
    procedure TForm1.Notification(AComponent: TComponent; Operation: TOperation);
    begin
    inherited Notification( AComponent, Operation );
    if ( Operation = opRemove ) and ( AComponent = FModalView ) then
    begin
    Self.Enabled := True;
    if Self.CanFocus then
    Self.SetFocus;
    FModalView := nil;
    end;
    end;<BR>
    procedure TForm1.Button1Click(Sender: TObject);
    begin
    FModalView := TForm2.Create(Self);
    FModalView.Show;
    Self.Enabled := False;
    end;
    </CODE>
    Das ist nur als Ansatz zu betrachten.
    Gruß, Fran

    Comment


    • #3
      @ Frank , guter Ansatz

      ich würde dann noch etws mehr Objektorientiert arbeiten.

      Im Hauptfofrmular :

      // der Aufruf

      procedure TForm1.Button2Click(Sender: TObject);
      var modalform : TForm2;
      begin

      modalform := TForm2.Create(self);
      modalform.ShowMySelf(Form1);

      end;

      im "modalen" Formular

      unit Unit2;

      interface

      uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs;

      type
      TForm2 = class(TForm)
      procedure FormClose(Sender: TObject; var Action: TCloseAction);
      private
      { Private-Deklarationen }
      myparentform :TForm;
      public
      { Public-Deklarationen }

      procedure ShowMySelf(parentform : TForm);
      end;

      var
      Form2: TForm2;

      implementation

      {$R *.dfm}

      { TForm2 }

      procedure TForm2.ShowMySelf(parentform : TForm);
      begin
      myparentform:= parentform;
      myparentform.Enabled:= false;
      self.Show;

      end;

      procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
      begin
      myparentform.Enabled:= true;
      end;

      Gruß Andrea

      Comment


      • #4
        sorry korrekter Weise sollte man in
        procedure ShowMySelf(parentform : TForm);

        der Sicherheit wegen das "const" nicht vergessen

        procedure ShowMySelf(const parentform : TForm)

        Comment


        • #5
          Schon nicht schlecht der Ansatz; der erste Ansatz sieht gut aus.
          Wie läßt sich das noch dahin erweitern, das das "Mutter-Fenster" solange wartet, bis das "Tochter-Fenster" beendet wurde (equivalent zum Showmodal).

          Beispiel (Mutter-Fenster startet Tochter-Fenster):

          VAR F : TadressenSuchen;
          Begin
          f:=TadressenSuchen.create(self);
          f.ShowMyself(self);
          //jetzt die Verarbeitung der Daten in Tadressensuchen
          if f.edit1.text='blub' then ....
          f.release;
          End;

          Durch das jetzt verwendete Showmyself wird das Fenster zwar angezeigt, aber nach Showmyself rennt das System gleich weiter bis zum release

          Comment


          • #6
            da du in dem Ansatz objektorientiert arbeitest,
            hast du das Mutterfenster -Objekt als Variable im Child.

            Im onclose des childs wird doch jetzt schon das Mutter fenster
            enabled , dort könnte man auch die Routine unterbringen.

            Hier sei jedoch gesagt , sollten es größere Datenmengen sein ,
            solltest du eine Klasse zur Kommunikation zwischen beiden schreiben

            Comment


            • #7
              Du hast Recht der Datenaustausch lässt sich auf anders bewerkstelligen.
              Aber ich habe im vorliegenden Fall noch ein Problem, welches einer Lösung bedarf, damit ich showmodal gegen showmyself tauschen kann:
              Wie stoppe ich die Verarbeitung des Mutterfensters, während das Tochterfenster geöffnet ist?

              Beispiel: Hauptfenster

              ....
              // f.showmodal;
              f.showmyself(self);
              query.refresh;
              ....

              Verwende ich das showmodal, so wird das query.refresh erst ausgeführt, wenn das Tochterfenster geschlossen wird (gewünschtes Verhalten). beim f.showmyself wird direkt danach das refresh ausgeführt (unerwünscht).
              Wie lässt sich also Ausführung des Mutterprozesses so lange anhalten

              Comment


              • #8
                indem du in deinem Mutterformular ein Ereignis(property) anlegst
                z.B onchildopen.
                und afterchildclose;
                in deren proceduren rufst du deine entsprechenden Sachen auf

                .....Kopfschüttel....

                Comment


                • #9
                  Also scheint ein direkter Ersatz des Showmodal nicht möglich und da ist einiges umzustrukturieren um das mit dem Showmyself auf die Reihe zu bringen (lokale Variablen des Events, welches Showmyself aufruft müssen, jetzt übergreifend durch zwei Events sichtbar gemacht werden). Das verkompliziert die Sache doch um einiges. Ich werde noch mal im der VCL Source des Showmodal nachschauen, ob sich da was machen lässt...

                  Comment


                  • #10
                    Okay,
                    laut Sourcecode im Tcustomform.showmodal besteht die Routine eigentlich aus ein wenig Buchhaltung (Focus merken, ev. aktive Drag/Drop abbrechen etc.) und dann
                    *show
                    *Warteschleife! bestehend aus application.handlemessage
                    *hide
                    gefolgt von aufräumender Buchhaltung.

                    Diese handlemessage reagiert in der aufrufenden Prozuedur wesentlich langsamer und träger als application.processmessage.
                    Hab's dann auch noch mal getestet:
                    Handlemessage wird ca. 3 bis 8x/Sekunde aufgerufen, während Processmessage schnell tausende mal/Sekunde gestartet abläuft.
                    Auch ist bei der Nutzung von Handlemessage nach diesen Test keine CPU Last feststellbar.

                    Damit scheint also mein Favorit zum showmodal sein:
                    f.showmyself(self);
                    repeat
                    Application.HandleMessage;
                    until f.Visible=False;

                    Das geht bestimmt noch etwas hübscher, aber ich werde es erst mal beobachten, ob diese Konstruktion zuverlässig ist und das gewünschte Verhalten hat

                    Comment


                    • #11
                      Also mit der Form-Vererbung kann ich das gwünschte (und funktionierende) "showmyself" mit modalem Verhalten auf meine gesamten Formulare übertragen.
                      Hier die Form-Definition, die ich für letzte Funktionstest verwendet habe:
                      type
                      TForm2 = class(TForm)
                      procedure FormClose(Sender: TObject; var Action: TCloseAction);
                      procedure FormShow(Sender: TObject);
                      private
                      myparentform :TForm;
                      public
                      procedure ShowMyModal(const parentform : TForm);
                      procedure FormCreate(Sender: TObject);
                      end;

                      implementation

                      {$R *.dfm}

                      procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
                      begin
                      inherited;
                      Action:=caFree;
                      if myparentform<>NIL then myparentform.Enabled:=True;
                      end;

                      procedure TForm2.ShowMyModal(const parentform : TForm);
                      Begin
                      myparentform:= parentform;
                      myparentform.Enabled:= false;
                      Show;
                      Repeat
                      Application.HandleMessage;
                      until NOT Visible;
                      End;
                      procedure TForm2.FormCreate(Sender: TObject);
                      begin
                      inherited;
                      myparentform :=NIL;
                      end;

                      procedure TForm2.FormShow(Sender: TObject);
                      begin
                      inherited;
                      SetWindowLong(Handle, GWL_ExStyle, WS_Ex_AppWindow); //jedes Fenster in die Taskleiste
                      end;

                      Bei meinen Tests ist mir bei dem neuen Fensterverhalten noch etwas aufgefallen, was die usability etwas steigern könnte, aber da mache ich gleich mal einen neuen Thread auf.

                      Vielen Dank allen, die sich die Zeit genommen habe, sich gedanklich mit meinem Problem zu beschäftigen und hier zur Lösung beigetragen zu haben.
                      Schönes Wochenend

                      Comment

                      Working...
                      X