Mutually calling DIALOGs

Post Reply
User avatar
Enrico Maria Giordano
Posts: 7355
Joined: Thu Oct 06, 2005 8:17 pm
Location: Roma - Italia
Contact:

Mutually calling DIALOGs

Post 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
manuramos
Posts: 219
Joined: Mon Dec 26, 2005 7:25 pm
Location: Jerez de la Frontera (Spain)

Post 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().
Nos Gusta Programar
User avatar
Greg Gammon
Posts: 105
Joined: Fri Jun 09, 2006 3:27 pm
Location: Bryan, Texas

Post 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.
manuramos
Posts: 219
Joined: Mon Dec 26, 2005 7:25 pm
Location: Jerez de la Frontera (Spain)

Post 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)
Nos Gusta Programar
User avatar
Greg Gammon
Posts: 105
Joined: Fri Jun 09, 2006 3:27 pm
Location: Bryan, Texas

Post 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
Gale FORd
Posts: 663
Joined: Mon Dec 05, 2005 11:22 pm
Location: Houston
Contact:

Post 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 )
User avatar
Enrico Maria Giordano
Posts: 7355
Joined: Thu Oct 06, 2005 8:17 pm
Location: Roma - Italia
Contact:

Post 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
Gale FORd
Posts: 663
Joined: Mon Dec 05, 2005 11:22 pm
Location: Houston
Contact:

Post 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.
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post 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.
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Enrico Maria Giordano
Posts: 7355
Joined: Thu Oct 06, 2005 8:17 pm
Location: Roma - Italia
Contact:

Post 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
Post Reply