Seite 1 von 1

Fenster schliessen

Verfasst: Di, 01. Aug 2006 14:45
von JanR
Hallo,

habe folgendes Problem. Ich rufe von einem Fenster über einen Button ein weiteres Fenster auf. Wenn ich das zweite Fenster über das X rechts oben schliesse, schliesst er das Fenster und arbeitet weiter. Im Beispiel gibt er eine MessageBox aus. Wenn ich allerdings das Fenster über einen Button schliessen will, kommt die MessageBox nicht. Was mache ich hier falsch? In der :close() methode des XbpDialogs steht das selbe drin wie in der activate() methode des XbpPushButton.

Hier der Quellcode:

Code: Alles auswählen

#include "appevent.ch"
#include "xbp.ch"

PROCEDURE AppSys()
RETURN


PROCEDURE Main()
   LOCAL n := 1

   oDlg1         := XbpDialog():new( ,, {50,30}, {300,200} ) 
   oDlg1:title   := "Parent is Application Window" 
   oDlg1:create() 
   oDlg1:close := {|| oDlg1:destroy()}

   oPB := XbpPushButton():new(oDlg1, oDlg1, {10,10}, {80,25})
   oPB:caption := "Test"
   oPB:create()
   oPB:activate := {|| Test(oDlg1, n)}

   nEvent := 0 
      DO WHILE nEvent <> xbeP_Close 
         nEvent := AppEvent( @mp1, @mp2, @oXbp ) 
         oXbp:handleEvent( nEvent, mp1, mp2 ) 
      ENDDO 
RETURN


FUNCTION Test(oDlg1,n)
   IF n == 1
      CreateNewWindow()
      MsgBox("Test")
   ENDIF
RETURN


FUNCTION CreateNewWindow(oDlg1)
   oDlg2         := XbpDialog():new(oDlg1 ,oDlg1, {200,30}, {300,200} ) 
   oDlg2:title   := "Parent is Application Window" 
   oDlg2:create() 
   oDlg2:close := {|| oDlg2:destroy()}   

   oPB := XbpPushButton():new(oDlg2, oDlg2, {10,10}, {80,25})
   oPB:caption := "Schliessen"
   oPB:create()
   oPB:activate := {||oDlg2:destroy()}

   nEvent := 0 
      DO WHILE nEvent <> xbeP_Close 
         nEvent := AppEvent( @mp1, @mp2, @oXbp ) 
         oXbp:handleEvent( nEvent, mp1, mp2 ) 
      ENDDO 
RETURN

Re: Fenster schliessen

Verfasst: Di, 01. Aug 2006 15:31
von AUGE_OHR
hi,
JanR hat geschrieben: In der :close() methode des XbpDialogs steht das selbe drin wie in
der activate() methode des XbpPushButton.

Code: Alles auswählen

      CreateNewWindow()

FUNCTION CreateNewWindow(oDlg1)
   oDlg2:close := {|| oDlg2:destroy()}   

   oPB:activate := {||oDlg2:destroy()}

   nEvent := 0 
      DO WHILE nEvent <> xbeP_Close 
         nEvent := AppEvent( @mp1, @mp2, @oXbp ) 
         oXbp:handleEvent( nEvent, mp1, mp2 ) 
      ENDDO 

RETURN
also ich meine das du oPB:activate := {||oDlg2:destroy()} nicht so
benutzten kannst. Das oDlg2:destroy() würde ich nach dem ENDDO
ansetzten und "nEvent <> xbeP_Close" durch ".NOT. lExit" zum
"schliessen" ersetzen.

Code: Alles auswählen

LOCAL lExit := .F.
...
   oDlg2:close := {|| lExit := .T.}   
...
*   oPB:activate := {||oDlg2:close()}
// sorry muss wie Hubert schreibt
   oPB:activate := {|| postappevent(xbeP_Close)}
...
   DO WHILE .NOT. lExit
...
   ENDDO
...
oDlg2:destroy()
gruss by OHR
Jimmy

Re: Fenster schliessen

Verfasst: Di, 01. Aug 2006 15:58
von brandelh
JanR hat geschrieben:

Code: Alles auswählen

#include "appevent.ch"
#include "xbp.ch"

PROCEDURE AppSys()
RETURN


PROCEDURE Main()
...
FUNCTION Test(oDlg1,n)
   IF n == 1
      CreateNewWindow() <- hier hängt das Fenster 2, bis es geschlossen wird.
      MsgBox("Test")
   ENDIF
RETURN

FUNCTION CreateNewWindow(oDlg1)
   ...
    nEvent := 0 
      DO WHILE nEvent <> xbeP_Close   // diese Ereignisschleife zieht !
         nEvent := AppEvent( @mp1, @mp2, @oXbp ) 
         oXbp:handleEvent( nEvent, mp1, mp2 ) 
      ENDDO 
RETURN
während des X oben rechts einen close-event auslöst, was die Fenster schön der Reihe nach schließt (hier hat die MSGBOX Zeit) wird im 2. Falle sofort der 2. Dialog zerstört, was automatisch auch den ersten ins nirwana schickt.

Grundsätzlich kann ich nur davon abraten, FUNCTION-CODE zu benutzen.
Außerdem soll man keine 2 Eventschleifen haben.
Ist es wirklich Absicht, dass das 2. Fenster in der Funktion Test(oDlg1,n)
stehen bleibt ?

Um den PushButton mit dem X-Button gleichzusetzen, muß man ihn den gleichen Event erzeugen lassen, also statt:

Code: Alles auswählen

oPB:activate := {||oDlg2:destroy()} 
muss man:

Code: Alles auswählen

oPB:activate := {|| postappevent(xbeP_Close)}
eingeben. Bei den Close sollte man auch nicht auf lokale Variablen referenzieren, da diese eigentlich zur Codeblockausführungszeit nicht mehr da sind. Sobald der Close-Event ausgelöst wird, gibt er als 3. Parameter das Fenster zurück, sodass man am besten definiert:

Code: Alles auswählen

oDlg2:close  := {|n1,n2,oXbp| oXbp:destroy()}
somit stimmt es immer.

Im Class-Code würde man für solche Verweise immer Instanzvariablen benutzen, diese sind solange verfügbar, wie das Objekt (Fenster etc.) da ist. Auch könnte man dann diese bei der postappevent() Steuerung genau benutzen, d.h. genau das gewünschte Fenster oder das gewünschte Kontroll angeben an das die Nachricht (event) gesendet werden soll.

Das alles funktioniert im function-Code nicht richtig.

Verfasst: Di, 01. Aug 2006 16:35
von brandelh
Hallo,

was mir noch auffällt:

Du gibst als parent und owner das Fenster selbst an, laut Handbuch muss dies jedoch die drawingarea sein !

Ich denke folgendes Programm verhält sich so, wie du es erwartet hast:

Code: Alles auswählen

#include "appevent.ch"
#include "xbp.ch"

PROCEDURE AppSys()
RETURN


PROCEDURE Main()
   LOCAL n := 1
   local oDlg1, oPB, nEvent, mp1:=NIL, mp2:=NIL, oXbp:=NIL

   set charset to ansi

   oDlg1         := XbpDialog():new( ,, {50,30}, {300,200} )
   oDlg1:title   := "Parent is Application Window"
   oDlg1:tasklist := .t.
   oDlg1:create()
   oDlg1:close := {|n1,n2,oXbp| oXbp:destroy()}

   oPB := XbpPushButton():new(oDlg1:drawingarea, , {10,10}, {80,25})
   oPB:caption := "Tester"
   oPB:create()
   oPB:activate := {|| Test(oDlg1, n)}

   nEvent := 0
   DO WHILE nEvent <> xbeP_Close
      nEvent := AppEvent( @mp1, @mp2, @oXbp )
      oXbp:handleEvent( nEvent, mp1, mp2 )
      // 2. Fenster wurde geschlossen
      if nEvent = xbeP_Close
         if oXbp = oDlg1
            msgbox("Programm ist zu Ende")
         else
            msgbox("CLOSE bei "+var2char(oXbp))
            nEvent := 0
         endif
      endif
   ENDDO
RETURN


FUNCTION Test(oDlg1,n)
   IF n == 1
      CreateNewWindow()
      MsgBox("Test - Fenster ist erzeugt.")
   ENDIF
RETURN nil


FUNCTION CreateNewWindow(oDlg1)
   local oDA, oDLG2, oPB
   oDlg2         := XbpDialog():new(oDlg1 ,oDlg1, {200,30}, {300,200} )
   oDlg2:title   := "Parent is Application Window"
   oDlg2:create()
   oDlg2:close := {|n1,n2,oXbp| oXbp:destroy()}

   oDA := oDlg2:drawingarea  // bei XbpDialog immer drawingarea angeben !!!!!

   oPB := XbpPushButton():new(oDA, , {10,10}, {80,25})
   oPB:caption := "Schließen"
   oPB:create()
   oPB:activate := {|u1,u2,oXbp| postappevent(xbeP_Close,,,;
                                          oXbp:SetParent():SetParent())}
RETURN nil

Verfasst: Di, 01. Aug 2006 17:58
von AUGE_OHR
hi,

Hubert hat ja nun eine "schöne" Lösung präsentiert.

Was mich allerdings wundert:
warum ist das "X" im "erzeugten" Fenster oben rechts "so klein" ?

gruss by OHR
Jimmy

Verfasst: Mi, 02. Aug 2006 8:40
von JanR
Vielen Dank Hubert und Jimmy.

Jetzt klappt es.


Grüsse,
Jan