Page 1 of 1

Mutually calling DIALOGs

Posted: Thu Jul 06, 2006 7:47 pm
by Enrico Maria Giordano
What is the correct way to close mutually calling DIALOGs? Try the following sample:

Code: Select all

#include "Fivewin.ch"


FUNCTION MAIN()

    TEST1()

    RETURN NIL


STATIC FUNCTION TEST1()

    LOCAL oDlg

    DEFINE DIALOG oDlg;
           TITLE "Test1"

    @ 1, 1 BUTTON "Switch to test2";
           ACTION ( oDlg:End(), TEST2() )

    ACTIVATE DIALOG oDlg;
             CENTER

    ? "Exiting from test1"

    RETURN NIL


STATIC FUNCTION TEST2()

    LOCAL oDlg

    DEFINE DIALOG oDlg;
           TITLE "Test2"

    @ 1, 1 BUTTON "Switch to test1";
           ACTION ( oDlg:End(), TEST1() )

    ACTIVATE DIALOG oDlg;
             CENTER

    ? "Exiting from test2"

    RETURN NIL
Thanks for any help.

EMG

Posted: Thu Jul 06, 2006 8:06 pm
by manuramos
Try this:

FUNCTION MAIN()

TEST1( 0 )

RETURN NIL


STATIC FUNCTION TEST1( hWnd )

LOCAL oDlg

IF hWnd # 0
PostMessage(hWnd,WM_CLOSE)
ENDIF


DEFINE DIALOG oDlg;
TITLE "Test1"

@ 1, 1 BUTTON "Switch to test2";
ACTION TEST2( oDlg:hWnd )

ACTIVATE DIALOG oDlg;
CENTER

? "Exiting from test1"

RETURN NIL


STATIC FUNCTION TEST2( hWnd )

LOCAL oDlg

IF hWnd # 0
PostMessage(hWnd,WM_CLOSE)
ENDIF


DEFINE DIALOG oDlg;
TITLE "Test2"

@ 1, 1 BUTTON "Switch to test1";
ACTION TEST1( hWnd )

ACTIVATE DIALOG oDlg;
CENTER

? "Exiting from test2"

RETURN NIL

You could use PostMessage() or directly SendMessage().

Posted: Thu Jul 06, 2006 8:20 pm
by Enrico Maria Giordano
Unfortunately that doesn't solve the problem. :-(

EMG

Posted: Thu Jul 06, 2006 9:00 pm
by Greg Gammon
I have done something similar with Dialogs that are called from multiple locations. I use STATIC oDlg1, oDlg2 etc and in any given function use oDlg1:end() etc. so that I can close any dialog from inside any function (for those dialogs that must be handled that way).

Hope that helps.

Posted: Thu Jul 06, 2006 9:02 pm
by manuramos
Effectivly it doesn't work. But this works correctly:

FUNCTION MAIN()

TEST1()

RETURN NIL


STATIC FUNCTION TEST1()

LOCAL oDlg
LOCAL lGo := .F.

DEFINE DIALOG oDlg;
TITLE "Test1"

@ 1, 1 BUTTON "Switch to test2";
ACTION (lGo := .T., oDlg:End())

ACTIVATE DIALOG oDlg CENTER
? "Exiting from test1"

IF lGo
TEST2()
ENDIF


RETURN NIL


STATIC FUNCTION TEST2()

LOCAL oDlg
LOCAL lGo := .F.
DEFINE DIALOG oDlg;
TITLE "Test2"

@ 1, 1 BUTTON "Switch to test1";
ACTION (lGo := .T., oDlg:End())

ACTIVATE DIALOG oDlg;
CENTER

? "Exiting from test2"

IF lGo
TEST1()
ENDIF


RETURN NIL

Dialogs don't mutally call each other but it's works fine. If you click the button the dialog closes it self and the other opens, if you click any "X" top right button the dialog closes without calling another dialog.
(Excuse my english)

Posted: Thu Jul 06, 2006 9:14 pm
by Greg Gammon
Actually i went back and looked at my code and its very similar to what manuramos has said....

ACTION oDlg:end(), lNext := .t.
END DIALOG

IF lNext
nextfunction()
ENDIF


yep...thats what I did too. Its a winner. I used STATIC dialog references on another issue.
G

Posted: Thu Jul 06, 2006 9:22 pm
by Gale FORd
You don't want to get down to many levels. How about this?


FUNCTION MAIN()
local bBlock := { || test1() }
do while bBlock != nil
bBlock := eval( bBlock )
enddo

RETURN NIL


STATIC FUNCTION TEST1()
local bBlock

LOCAL oDlg

DEFINE DIALOG oDlg;
TITLE "Test1"

@ 1, 1 BUTTON "Switch to test2";
ACTION ( bBlock := { || test2() }, oDlg:End() )

ACTIVATE DIALOG oDlg;
CENTER

? "Exiting from test1"

RETURN( bBlock )


STATIC FUNCTION TEST2()
local bBlock

LOCAL oDlg

DEFINE DIALOG oDlg;
TITLE "Test2"

@ 1, 1 BUTTON "Switch to test1";
ACTION ( bBlock := { || test1() }, oDlg:End() )

ACTIVATE DIALOG oDlg;
CENTER

? "Exiting from test2"

RETURN( bBlock )

Posted: Thu Jul 06, 2006 9:28 pm
by Enrico Maria Giordano
This is on oversimplification and doesn't still solves my problem, sorry. I actually don't know what is the next function to call inside TEST1() and TEST2().

EMG

Posted: Thu Jul 06, 2006 9:51 pm
by Gale FORd
It seems to me that if you call test1() from test2(), then test2() from test1(), etc you will keep getting farther down the call stack. You either need to pass a codeblock along to an arbitrator or use the code like I sent above.

Posted: Fri Jul 07, 2006 6:53 am
by Antonio Linares
Enrico,

IMO there is nothing wrong with your code. You are managing modal dialogboxes so the execution waits until you return from the called function.

Modal dialogboxes stop the execution (its a Windows API modal called function) until you exit from them.

As Gale said, the stack will grow and grow until you don't exit from them. The only solution for this is to use non modal dialog boxes.

Posted: Fri Jul 07, 2006 9:31 am
by Enrico Maria Giordano
Thank you. This is a working sample, at last:

Code: Select all

#include "Fivewin.ch"


FUNCTION MAIN()

    LOCAL oWnd

    DEFINE WINDOW oWnd;
           FROM 1000, 1000 TO 1000, 1000

    ACTIVATE WINDOW oWnd;
             ON INIT ( oWnd:Hide(), TEST1( oWnd ) )

    RETURN NIL


STATIC FUNCTION TEST1( oWnd )

    LOCAL oDlg

    LOCAL lQuit := .T.

    DEFINE DIALOG oDlg;
           TITLE "Test1"

    @ 1, 1 BUTTON "Switch to test2";
           ACTION ( lQuit := .F., oDlg:End(), TEST2( oWnd ) )

    ACTIVATE DIALOG oDlg;
             VALID ( MSGINFO( "Exiting from test1" ),;
                     IF( lQuit, oWnd:End(), ),;
                     .T. );
             CENTER NOMODAL

    ? "Immediately exit from test1"

    RETURN NIL


STATIC FUNCTION TEST2( oWnd )

    LOCAL oDlg

    LOCAL lQuit := .T.

    DEFINE DIALOG oDlg;
           TITLE "Test2"

    @ 1, 1 BUTTON "Switch to test1";
           ACTION ( lQuit := .F., oDlg:End(), TEST1( oWnd ) )

    ACTIVATE DIALOG oDlg;
             VALID ( MSGINFO( "Exiting from test2" ),;
                     IF( lQuit, oWnd:End(), ),;
                     .T. );
             CENTER NOMODAL

    ? "Immediately exit from test2"

    RETURN NIL
EMG