Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Why is program running past a form's load.

Status
Not open for further replies.

stanlyn

Programmer
Sep 3, 2003
945
US
Hi,

I'm having an issue with "why" is program control flowing past a form load when the form is still up.

1. private pcMyVar
2. pcMyVar='VarValue'
3. do form 'test' with pcMyVar && the form loads as expected
4. messagebox('MyVar is:' + pcMyVar, 0, 'Var Value')

Note: pcMyVar gets changed from decisions made in the form

The problem is line 3 is executed and while the form is still on screen, line 4 is also executed. I expect line 4 to be executed after closing the form.

I've tried setting the form as InScreen, InTopLevel and as AsTopLevel with same results. Also played a little with a read events. The form is loaded from a menu.

Thanks for your help...
Stanley



 
Stanley,

Are you sitting down? The reason I ask is that, when you see how easy it is, you might fall off your chair.

Forget about InScreen, InTopLevel and AsTopLevel. You need to make the form modal.

And the way to do that is to set the form's WindowType to 1.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Yes Mike, I know that, (just didn't mention it), because I need it as modeless. So, how do I construct that?

Thanks,
Stanley
 
Stanley, what you are asking for can't be done.

If a form is modeless, your application will continue to execute after the form has loaded. That's what modeless means (well, not exactly, but close enough). The sequence of actions will be (approximately):

1. DO FORM command

2. Form will execute its Load, then the Inits for each of its controls, then the form's Init, then certain other events (SetFocus, Activate, etc.)

3. The form is now visible on the screen, ready to receive events.

4. The line in the calling program following DO FORM will execute.

That is what you are seeing.

If the form is modal, the above is all true, except that execution is suspended after step 3; it proceeds to step 4 only after the form has been released.

In short, you can't have it both ways.

Perhaps you could explain why you want the form to be modeless, but also want it not to execute the line after DO FORM while the form is still on the screen. We might then be able to suggest a solution.

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Stanley, you say you want the form to be modeless. Is that because you already have other forms on the screen, and you want the user to interact with all the open forms while your "test" form is open? But you still want execution to be suspended until "test" is closed?

If so, the solution is to execute READ EVENTS immediately after your DO FORM "test". You will also need a CLEAR EVENT, typically in the code that releases the form or in its Destroy event.

Or, maybe what you really want is for the message box (as per line 4 of your code) to display the values while "test" is running - and this is for debugging purposes rather than part of the application's functionality? If so, you could put a button on the form, and execute the message box from its Click event. Or you could do without the message box; instead, put a breakpoint in your code at the end of the Init (or the end of the Load perhaps); then examine the relevant variables in the debugger.

But I'm just guessing at what you want to achieve.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Well, the type of forms having a result should be modal, like the messagebox itself is. In fact that's one of the main reasons it is modal, also because it requires your intention and intentionally locks out all other current forms.

Anyway, nonmodal forms are what makes an application more dynamically usable, so your intention is fine.

I don't second using READ EVENTS for that purpose, instead say bye bye to a linear main code running and rethink the whole concept of windows forms. Who needs an answer? Most often its a calling form, so you should pass that in, pass in THISFORM from the form starting the nonmodal form., You may even not need to pass in a variable then, because the newly started nonmodal form may use a form property of the calling form as controlsource and so the calling form can even know every in between stat of its own property, as it is bound to another forms control.

The complicated part of this is now you depend on the caller form not to release before the new form ends. But aside of that problem, in OOP it's much better to work with objects, which combine data and behaviour, so you could also start up another class instance and pass that forth and back. What comes in play here could be a overall supervisor, a form handler. The only thing to pay attention about is the scoping of such objects, the forms etc. One other key word to know is callback. This is rather what you do multiple times in an asynchronous running secondary thread, but can also apply the concept to called forms. When calling you also pass in the info which other object expects a callback into some mehtod or the setting of a certain property, which could also trigger some behaviour via having an assign method.

If you want your application to have multiple forms up and running, interacting with each other and staying responsive for users to use them in a non linear fashion, but in parallel, then you shouldn't think about suspending and waiting for a result, you should think of going on with something else or ending code to go into the already running READ EVENTS event waiting "loop". The called form has to become an active part of this and either know or as I already suggested get said what to do in the end.

You have many possibilities and don't need to do it as suggested, there are many ideas out there and obvious, if you break through your linear thinking. One thing is for sure though, you can't let retun code follow right away and put yourself into a sleep mode like read events does to pick up there when the nonmodal form ends. This is like wanting to have the cake and eat it, too. No, you have to stop, let READ EVENTS take over and program the called form in some way to call back.

If you have the difficulty, you don't control the code of the called form, it's a third party thing, then you have to make use of bindevents to react to this forms destroy event, for example, but please simply forget about the idea you can wait with something until the form ends and let code execution continue right after the DO FORM. What makes things easier is also staying off of DO FORM and rather go for OOP the full monty and have form classes you instanciate. That gives you a very powerful way to act on the form before you set it visible or call its Show method. Instead of passing in info you can set form properties, the form becomes your puppet, as you have a form object reference.

Bye, Olaf.

Notice: You already make heavy use of the nonlinear way of code execution, if you ever programmed more than one button on a form and thereby have alternative code executing depending on which button a user clicks. If a form is nonmodal that already means you know the procedure of starting a form, which after load does nothing more, so the callstack goes up to the READ EVENTS and then nothing happens and what happens next depends on which button is clicked. You already make use of OOP all the way in that respect.
 
To your question on the modal vs. modeless and how to have the 'modeless' behave similar to the modal. I do this in my application. I do not have any modal forms -- all are modeless. I call the form with the following:

Code:
LOCAL loChildForm
DO FORM MyModelessForm WITH thisform TO loChildForm
thisform.ChildForm = loChildForm
BINDEVENT(loChildForm, "QueryUnload", thisform, "ReleaseChildForm")
BINDEVENT(loChildForm, "Release", thisform, "ReleaseChildForm")

In the child form, I defined a new property CallingForm and assign the value in the form's Init() method:

Code:
LPARAMETERS toCallingForm
thisform.CallingForm = toCallingForm
...
[/code ]

In the parent form, I defined the property ChildForm, and the Method ReleaseChildForm().  The code for this method is:

[code]
IF !ISNULL(thisform.ChildForm) .AND. VARTYPE(thisform.ChildForm) = "O"
	UNBINDEVENT(thisform.ChildForm, "QueryUnload", thisform, "ReleaseChildForm")
	UNBINDEVENT(thisform.ChildForm, "Release", thisform, "ReleaseChildForm")
	thisform.ChildForm.Release()
ENDIF
thisform.ChildForm = .NULL.

In the Close button on the child form, I execute the following to pass values back to the parent form:

Code:
RAISEEVENT(thisform.CallingForm, "OnFormMyModelessForm", MyReturnValue1, MyReturnValue2, ...)

In the parent form, I defined the custom method, OnFormMyModelessForm() with the following:

Code:
LPARAMETERS tMyReturnValue1, tMyReturnValue2, ...
thisform.ReleaseChildForm()
...
[/code ]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top