Seite 1 von 1

modaler xbpDialog()

Verfasst: Di, 05. Sep 2006 9:27
von mkersch
Hallo Forenmitglieder,

habe bei der Programmierung eines "Modalen Dialogs" Probleme.

Was mach ich falsch ?



Ich möchte über einen Hauptdialog mittels Button's in Unterdialoge
verzweigen.
Im Unterdialog sollen alle anderen Fenster gesperrt sein d.h. erst nach
beenden dieses Dialog's können wieder andere Fenster gewählt werden.


Das Sample Modality habe ich mir bereits angeschaut.

Für Eure Hilfe im Voraus vielen Dank.

mfg.

Michael

Verfasst: Di, 05. Sep 2006 11:07
von Rolf
Hi Michael,

bei mir funktioniert es auf diese Art

Code: Alles auswählen

/************************************************************
        Name :  Init
        Does :  KONSTRUKTOR
************************************************************/
METHOD dlgTexte:init( oParent, oOwner, aPos, aSize, aPP, lVisible)

    oParent := AppDesktop()
    oOwner := SetAppWindow()

    //-- Hauptdialog
    ::oDialog           := XbpDialog():new( oParent, oOwner, aPos, aSize, aPP, lVisible )
    ::oDialog:taskList  := .F.
    ::oDialog:sysMenu   := .T.
    ::oDialog:minButton := .T.
    ::oDialog:maxButton := .T.
    ::oDialog:border    := XBPDLG_SIZEBORDER
    ::oDialog:Title     := ""

RETURN self
/************************************************************
        Name :  create
        Does :  KONSTRUKTOR
************************************************************/
METHOD dlgTexte:create( oParent, oOwner, aPos, aSize, aPP, lVisible )

    //-- Dialog create
    ::oDialog:create()
    ::oDialog:drawingArea:SetFontCompoundName( FONT_HELV_SMALL )

    //** SHOW
    ::oDialog:show()
    ::oDialog:setModalState(XBP_DISP_APPMODAL)

    //-- Focus setzen
    ::oOldAppWindow := SetAppWindow( ::oDialog )
    //::oOldAppFocus := SetAppFocus(  ::oSleName1 )

    //-- Eventhandler
    nEvent := xbe_None
    DO WHILE .t.
   	nEvent := AppEvent ( @mp1, @mp2, @oXbp )
        oXbp:HandleEvent ( nEvent, mp1, mp2 )

        do case
	   case nEvent == xbeP_Close
		EXIT
        endcase
    ENDDO
RETURN self
/************************************************************
DESTROY
************************************************************/
METHOD dlgTexte:destroy()
    //-- Aufräumen
    ::oDialog:setModalState(XBP_DISP_MODELESS)
    ::oDialog:destroy()
    SetAppWindow(::oOldAppWindow)
    //SetAppFocus(::oOldAppFocus)
RETURN self
Grüße Rolf

Verfasst: Di, 05. Sep 2006 11:43
von mkersch
Vielen Dank für die Antwort.

Ich mache es ähnlich, funktioniert bei mir leider nicht !

Code: Alles auswählen

FUNCTION test_1()
   LOCAL nEvent, mp1, mp2
   LOCAL oDlg2, oXbp, drawingArea, aEditControls := {}

   oDlg2 := XbpDialog():new(AppDesktop()  ,SetAppWindow() , {192,1}, {800,600}, , .T.)
   oDlg2:taskList := .F.
   oDlg2:sysMenu := .T.
   oDlg2:minButton := .T.
   oDlg2:maxButton := .T.
   oDlg2:border    := XBPDLG_SIZEBORDER

   oDlg2:title := "Formular 1"
   oDlg2:create()

   drawingArea := oDlg2:drawingArea
   drawingArea:setFontCompoundName( "8.Arial" )


   oDlg2:show()
    n_dummy := oDlg2:setModalState(XBP_DISP_APPMODAL)


   oXbp := XbpStatic():new( drawingArea, , {312,420}, {84,48} )
   oXbp:caption := "Test 1"
   oXbp:clipSiblings := .T.
   oXbp:options := XBPSTATIC_TEXT_VCENTER+XBPSTATIC_TEXT_RIGHT
   oXbp:create()


  /*
   * XBP der gerade Fokus hat sichern und Fokus auf Sle setzen
   */
   SetAppWindow( oDlg2 )
   //oFocus := SetAppFocus( oDlg )

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

  /*
   * Dialogfenster nicht-modal schalten.
   * WICHTIG: Dadurch wird das Owner Fenster entsperrt
   */
   oDlg2:setModalState( XBP_DISP_MODELESS )

  /*
   * Daten vom Sle holen, Dialogfenster freigeben und
   * Fokus auf vorherigen XBP setzen
   */
   //cString := oSle:getData()
   oDlg2:destroy()
  // SetAppFocus( oFocus )


RETURN(0)

Verfasst: Di, 05. Sep 2006 12:04
von Rolf
Hi Michael,

hab leider auch keinen Fehler gefunden.
Es könnte noch an dem Owner oder Parent liegen.
Da probier ich auch nur immer rum bis es funktioniert.

Es gibt auch von Alaska ein Bsp. unter:
Alaska\XPPW32\SOURCE\SAMPLES\BASICS\WINDOWS\Modality.prg

das könnte auch helfen

Grüße
Rolf

Verfasst: Di, 05. Sep 2006 12:19
von andreas
Hallo Michael,

ich benutze auch modale Fenster.
Du übergibst als Owner den Befehl SetAppWindow().

Ich mache es anders.

1. Kein Parent
2. Owner als Variable übergeben, die für die Erstellung des Vorherigen Fensters benutzt wurde oder wenn du Methode zum Aufruf benutzt, dann SELF.
3. ::setModalState(XBP_DISP_APPMODAL) vor dem show().

Verfasst: Di, 05. Sep 2006 12:58
von mkersch
Vielen Dank für die Hilfe.

Funktioniert leider noch nicht.

Was mach ich falsch ?

Aufruf:

Code: Alles auswählen

  oXbp1:activate := {|| test_1(oDlg:setOwner()) }


FUNCTION test_1(my_owner)
   LOCAL nEvent, mp1, mp2
   LOCAL oDlg2, oXbp, drawingArea, aEditControls := {}

   oDlg2 := XbpDialog():new(  ,my_owner  , {192,1}, {800,600}, , .T.)
   oDlg2:taskList := .F.
   oDlg2:sysMenu := .T.
   oDlg2:minButton := .T.
   oDlg2:maxButton := .T.
   oDlg2:border    := XBPDLG_SIZEBORDER

   oDlg2:title := "Formular 1"
   oDlg2:create()

   drawingArea := oDlg2:drawingArea
   drawingArea:setFontCompoundName( "8.Arial" )


    n_dummy := oDlg2:setModalState(XBP_DISP_APPMODAL)
    oDlg2:show()


   oXbp := XbpStatic():new( drawingArea, , {312,420}, {84,48} )
   oXbp:caption := "Test 1"
   oXbp:clipSiblings := .T.
   oXbp:options := XBPSTATIC_TEXT_VCENTER+XBPSTATIC_TEXT_RIGHT
   oXbp:create()


  /*
   * XBP der gerade Fokus hat sichern und Fokus auf Sle setzen
   */
   SetAppWindow( oDlg2 )
   //oFocus := SetAppFocus( oDlg )

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

  /*
   * Dialogfenster nicht-modal schalten.
   * WICHTIG: Dadurch wird das Owner Fenster entsperrt
   */
   oDlg2:setModalState( XBP_DISP_MODELESS )

  /*
   * Daten vom Sle holen, Dialogfenster freigeben und
   * Fokus auf vorherigen XBP setzen
   */
   //cString := oSle:getData()
   oDlg2:destroy()
  // SetAppFocus( oFocus )


RETURN(0)
mfg.

Michael

Verfasst: Di, 05. Sep 2006 13:04
von Jan
Ich bin mir jetzt nicht ganz sicher, und habe leider im Moment meinen Alaska-Rechner nicht greifbar. Aber da war doch irgendwas mit :border? Ich bekomme das jetzt nicht so hin, war das mit maximal vergrößern, oder mit modal? Das ging jedenfalls bei manchen Border-Einstellungen nicht bzw. erforderte eine bestimmte Einstellung.

Jan

Verfasst: Di, 05. Sep 2006 13:55
von Rolf
Hi Michael,

ich hab den ersten Quelltext von Dir mal eingebunden und er funktioniert bei mir.
Es liegt wahrscheinlich an dem darüberliegenden Dialog.

Grüße Rolf

Verfasst: Di, 05. Sep 2006 14:04
von brandelh
Hi,

in den Beispielen gibt es den About-Dialog.
Das ist ein Modaler Dialog, den ich schon lange verwende.

Es hängt auch vom Owner und Parent ab, sowie einer eigenen Eventloop (vermute ich jetzt mal).

Re: modaler xbpDialog()

Verfasst: Di, 05. Sep 2006 15:35
von AUGE_OHR
hi,
mkersch hat geschrieben: habe bei der Programmierung eines "Modalen Dialogs" Probleme.
versuche mal

Code: Alles auswählen

oDlg := XbpDialog():new( AppDeskTop(),oParent, aPos, aSize, , .F.)
oDlg:moveWithOwner := .T.
damit wird das neue Fenster auf dem oParent "festgenagelt"

gruss by OHR
Jimmy

Verfasst: Mi, 06. Sep 2006 8:01
von mkersch
Hallo Forenmitglieder,

nach einigen Versuchen komme ich zu folgenden Ergebnis.

Wird ein Dialog aus einen CRT Fenster geöffnet so kann dieser Dialog
in den Modal-Modus gebracht werden.

Öffne ich einen ersten Dialog aus den CRT Fenster und von diesen Dialog
noch einen weiteren, dann kann der zuletzt erzeugte Dialog nicht in den
Modal-Modus gebracht werden (auch nicht das Beispiel "About-Dialog")
d.h. die beiden Dialoge können mittels Maus gewählt werden.

mfg.

Michael

Verfasst: Mi, 06. Sep 2006 8:14
von Martin Altmann
Hallo Michael,
den selben Effekt kannst Du auch bei nicht-CRTs (also GUI) erreichen - und zwar genau dann, wenn Du bei dem parent/owner einen Fehler machst!
Wenn Du also den falschen parent/owner hinterlegt hast, dann hast Du genau diesen Effekt.
Wer sind denn der parent und owner Deines zuletzt geöffneten Fensters? Dein Hauptfenster oder das Fenster, von dem aus Du das letzte CRT geöffnet hast?

Viele Grüße,
Martin

Verfasst: Mi, 06. Sep 2006 8:15
von brandelh
Hallo,

wenn das so ist, dann ist bei dir das 1. CRT Fenster der Owner des Modalen Dialoges. Das Modale Fenster sperrt seinen Owner automatisch.
Du must deinen 2. Dialog als Owner eintragen, damit die automatische Sperrung funktioniert, oder aber das 2. Fenster einfach disablen (manuell sperren).
Beim meinem GUI-Modell (abgeleitet aus der MDI-Demo) werden die Childs des Hauptprogrames allerdings auch automatisch gesperrt ... :?

Verfasst: Mi, 06. Sep 2006 11:06
von mkersch
Vielen Dank für Eure Antworten.

Ich muß leider gestehen das mit den PARENT und OWNER habe ich noch
nicht ganz verstanden. :cry:

Kann ich diesen Zusammenhang in der Dokumentation nachlesen ?

Bzw. kann jemand diesen Zusammenhang einfach erklären ?


mfg.

Michael

Verfasst: Mi, 06. Sep 2006 11:17
von Martin Altmann
Hallo Michael,
ich versuche mal, es einfach zu erklären.
Wenn Du ein Dialog erzeugst, gibst Du als Paramter ja auch den Parent und den Owner an. Das "Problem" bei einem modalen Fenster ist ja, dass es modal zu seinem Owner wird. Das bedeutet, dass das modale Fenster im Vordergrund liegt und der Owner wird disabled, kann also nicht aktiviert werden.
Wird das modale Fenster geschlossen, wird automatisch der Owner aktiviert.
Hast Du nun also das Problem, dass Du ein Hauptfenster A hast (Deine Anwendung) und dort einen modalen Dialog B aufrufst, dann muss bei diesem Dialog B der Owner A eingetragen sein. In diesem Fall wird dann Dein Hauptfenster deaktiviert und B liegt im Vordergrund vor A.
Rufst Du jetzt aus dem Fenster B einen modalen Dialog C auf und gibst dort als Owner ebenfalls A an, hast Du ein Problem:
Das Hauptfenster A wird deaktiviert (ist es ja schon) und C liegt im Vordergrund von A. C ist jedoch nur modal zu A und nicht zu B - Du kannst also beliebig zwischen den Fenstern B und C wechseln :!:
Schlimm wird es, sobald Du das Fenster C wieder schließt - dann wird nämlich der Owner A wieder aktiviert :!: Du hast dann also ein aktives A und ein teilweise modales Fenster B, das immer im Vordergrund liegt - man kann aber weitere Menüpunkte aus dem Fenster A aufrufen :!:
Als Owner muss bei verschachtelten modalen Dialogen also immer das Fenster angegeben werden, aus dem heraus der modale Dialog aufgerufen wurde :!:
In Deinem Beispiel muß der Owner von B A sein und der Owner von C ist B!

Viele Grüße,
Martin

Verfasst: Mi, 06. Sep 2006 11:46
von Manfred
Hi,

ist vielleicht vergleichbar mit einem Schrank. Der hat eine Schublade, die geöffnet werden muß. (Schublade gehört zum Schrank) In der Schublade ist eine Kassette. (Die gehört der Schublade) In der Schublade ist ein Buch (Gehört zur Kassette). Wenn die Reihenfolge nicht eingehalten wird, dann gibt es Chaos.

Oder die russischen Püppchen. Immer nach und nach rausholen und wieder reinstecken.

Habe ich jetzt mal so eingeworfen. Ob es hilft weiß ich auch nicht.

Verfasst: Mi, 06. Sep 2006 18:18
von andreas
Hallo Michael,

versuche deine Zeile

Code: Alles auswählen

  oXbp1:activate := {|| test_1(oDlg:setOwner()) } 
so zu ändern:

1.

Code: Alles auswählen

  oXbp1:activate := {|| test_1(oDlg) } 
oder

2.

Code: Alles auswählen

  oXbp1:activate := {|| test_1(self) } 
Mit deinem Befehl
oDlg:setOwner()
fragst den Owner von deinem 1. Fenster. Du muss aber das 1. Fenster als Owner angeben.

Verfasst: Mi, 06. Sep 2006 18:23
von Tom
Wer mit Modalitäten 8) nicht zurechtkommt, kann auch sowas machen:

Code: Alles auswählen

PROC MeinHauptfenster()

.. wird in "oDialog" gespeichert

MeinUnterfenster(oDialog)

oDialog:Destroy() // usw.
RETURN

PROC MeinUnterfenster(oOwner)
oOwner:Disable()

... Unterfenster bauen, anzeigen, löschen usw.

oOwner:Enable()
RETURN
"Modalität" für Fußgänger. :D