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 strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

quit application

Status
Not open for further replies.

Koen Piller

Programmer
Jun 30, 2005
841
NL
Hi,
I want to offer my users the option to end the application, running.
Situation is:
On my mainform a selectionform is activated with a selection combobox.
When users click the Quit button, the QueryUnload is activated with following code:
Code:
If Isnull(Thisform.cboZorg.Value)
    lcMessage =  "You have not yet made a selection,"+Chr(10)+Chr(13)+;
        "without this the programm can not work correctly"+chr(10+chr(13)+"Is that correct?"

    m.lnAnswer = Messagebox( m.lcMessage , 4+32+0, "Take care" )  &&  Yes = 6, No = 7
    Do Case
        Case m.lnAnswer = 6
            m.llClick = .T.
        Case m.lnAnswer = 7
    Endcase
Else
    m.llRet = .T.
Endif

Do Case
    Case m.llRet = .F. And m.llClick = .T.
        m.llRet = .T.
        Clear events
    Case m.llRet = .F. And m.llClick = .F.
        Nodefault
        m.llRet = .F.
Endcase

Return m.llRet

How ever the "Clear Events" gets not activated, the form is closed and the program continues....
How to quit? ( I was always told not to use 'quit' in an application, and to use it only to end a VFP session ) Seems that this is an exception to that rule. Correct?

Regards,
Koen
 
Koen,

There are several points here. First, QueryUnload does not return .T. or .F. Or, rather, if it does return a value, there is no opportunity for that value to be tested. Once QueryUnload has fired, the only way to prevent the form unloading is to issue NODEFAULT.

I don't see you setting an initial value to llRet or llClick. You are setting llRet to .T. if the selection has been made, but you are not setting it to .F. if it hasn't. Similarly, you are setting llClick to .T. if the user answers Yes, but not to .F. if they answer No. Presumably you are making those settings in some code that you have now shown here. (That must be the case, otherwise you would have received a "variable not found" error.)

More to the point, as far as I can see, your final DO CASE construct does not allow for the case of the user failing to make a selection, that is, the case where llRet is .T. As a result, the NODEFAULT will never be executed, so the form will always exit without the CLEAR EVENTS.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Also, there is no problem with using the QUIT command if your intention is to quit... I'm quite certain that it is in EVERY program I have ever written.
 
I agree. There is no particular problem in using QUIT. It's just that it is often not done. More likely, you will do CLEAR EVENTS, then do all your clean-up, then just run off the end of the main PRG.

The main times that I use QUIT is if I need to close down prematurely, for example, if I detect at start-up that some needed files are missing. It might also be used in an error-handler. But it is OK to QUIT at the end of your main program as well, provided you have done all your clean-up (committing buffers, ending transactions, etc.)

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mike,

llRet was issued on the first line with
Code:
Local llRet as Logical
which makes it by default to .F.

For the final do case ... endcase:
case m.llRet = .F. And m.llClick = .T. = user selected yes
case m.llRet = .F. and m.llClick = .F. = user selected no and does not want to quit -> nodefault

I don't want only the form to be stopped, I want also the application to be stopped.
so I was under the impression that once clear events was issued the program would return to the clear event in my startup after which the clear up code for the database is located.
Since the program will not return to the clear events after the read events in the programm1, I will / must recode and put the clear up code in a separate method which to be called in this case and after that a quit.

Regards,

Koen
 
Well, and there it is again, the misconception QUIT quits immediately. Quit does not:

Code:
o1 = CreateObject("app")

o2 = CreateObject("baseform")
o2.Show(2)

Quit
MessageBox("bye")

Define class anything as control
   Procedure Destroy()
       MessageBox( Sys(16))
   Endproc       
EndDefine 

Define class app as custom
   Procedure Destroy()
       MessageBox( Sys(16))
   Endproc       
EndDefine 

Define class baseform as form
   Add Object control1 as anything
   
   Procedure queryunload()
       MessageBox( Sys(16))
       If thisform.ReleaseType <>2
          If MessageBox("sure?",4+256,"really close form?") = 7
             nodefault
          Endif
       endif
   EndProc
Enddefine

And Koen, in QueryUnload you can decide via ReleaseType when you want and when you don't want to hinder end of the application with the help of ReleaseType.

Play with this example code, eg use ON SHUTDOWN QUIT instead of QUIT itself, then close the VFP IDE vs the mainform, to see the form distinguishes between closeing the application or the form.

Bye, Olaf.

Olaf Doschke Software Engineering
 
So to explain this:

The QUIT cuases a release of everything, variables, instanciated objects, etc. But that means the usual events are triggered. That's the Destroy event in general and the QueryUnload event in the special case of forms. Add more forms and each forms QueryUnload runs.

You do your tidying up in destroy events of all the classes you design and you can do a final tidying up in the application objhect destry, just make sure that's the first object you instanciate, and it'll be the last destroyed.

As it happens this way, and it doesn't matter if it happens because the command was QUIT or because the main application screen [x] was clicked, you get into Queryunload and react according to ReleaseType. It's a matter of your choice and tastes and how you usually want your security exit question to appear or not appear, whether you do that as I did in this example when ReleaseType<>2. You can also add a property to your form that signals QueryUnload it's okay for the form to release without security question, after you saved buffered changes for example, you can also make this depend on form.closable, etc. That's where you're free to establish the rules you need or want.

Just note QUIT does not quit immediately, what is true is, that you never get to the Messagebox("bye"), what also is true that no matter if you hinder the form to close when you would do nodefault there, your exe or VFP9.exe will quit and there'd be the need for a deep dive into a bag of tricks involving to bind to Windows events and canceling them, but you actually don't need code after READ EVENTS nor do you need CLEAR EVENTS, you can work with QUIT in any situation, therefore I made ON SHUTDOWN QUIT the norm and recommend it.

Bye, Olaf.

Olaf Doschke Software Engineering
 
I second Olaf's post.
I used QUIT conditionally, that is when it was compiled EXE, and RETURN when the program was run in IDE.
However, I always did the clean-up before either of the two exits: released all objects (visible - e.g. forms - or not) I had created on the run, class libs, removed added custom properties from the _SCREEN object, etc., no matter IDE or EXE.

Another thing I have to add: AFAIK, VFP is not - and has never been - strong-typed.
That means that all the explicitly declared new memvars are of type "U".
Thus, adding "As Logical", per my experience, won't have any effect. (Albeit adding "As Exception" did work, somehow, at least the PEMs list dropped down in the code editor when IntelliSense was on... ;-))

So, I always explicitly assigned the initial values to my newly declared memvars right after their declaration. Thus, I'd recommend the following:
Code:
LOCAL llRet, llClick
llRet = .F.
llClick = .F.
Then you'd know for sure they are of Boolean type and initialized with False.

Just my 2 cents :)

Regards,

Ilya
 
all the explicitly declared new memvars are of type "U".

Actually, that's not true. If you declare a variable but don't give it a value, it will be of type logical. Both TYPE() and VARTYPE() will return L.

But it is good practice always to assign an initial value to a variable.

Adding an AS clause to your declaration (e.g.[tt] LOCAL MyVar AS Character[/tt]) doesn't change that. The AS clause is intended for Intellisense, not for defining the variable's type.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Right, VARTYPE() may return "L", or rather Debugger/Locals would show you .F. as a value.
However, I've seen that same VARTYPE() returning "U" ("Undefined", IMS, or something along these "Un-xxx" lines) on uninitialized, newly declared memvar.
Can't show here the code sample coz ain't got it (nor VFP) on hands right now, but remember very vividly seeing it in either main VFP IDE's screen (after
Code:
?VARTYPE(MemVar)<Enter>
or
Code:
WAIT WINDOW [MemVar VARTYPE = "]+VARTYPE(scrMemVar)+["]

... or... what's it they say goes 1st with eyesight's being 2nd? :-( ACOCRS...)

Regards,

Ilya
 
And - right, adding As <data type> is "for your convenience" only. So, if you add As Form/Exception/Grid/Object/whatnot - it'll work in IDE/Editor as popup list, and only if you have this IntelliSense selection on (I once turned it off, back in VFP6... Andy Kramek scolded me for that on another forum...)

Regards,

Ilya
 
The "U" type results when the variable you test does not even exist. Vartype(fdjkssdjk) is "U", unless you declare fdjkssdjk.

More intellisense

Code:
*type this...
LOCAL loVar as VisualFoxpro.
* and at that point intellisense will list a few further VFP classes of objects you find in the context of the IDE itself, the project manager, etc.
* useful specifically for project hooks

But yes, this is not a declaration, you still need to instantiate such an object.

Your own classes are allowed, too, when you also specify the OF library.vcx part. That way you also get intellisense for your user defined method names and parameters.

Registering a SOAP XML web service with the task pane also shows how to add even more intellisense to the foxcode.dbf and all in all that increases code quality. Especially since the compiler believes you whatever method names and parameters you write (and how many), errors in that regard always only trigger exceptions at runtime because VFP is weakly typed.

Bye, Olaf.



Olaf Doschke Software Engineering
 
Ilya,

Mike is fully correct, all variables when instantiated with "Local" are Logical and .F. by default, so also
Code:
Local lcFile as String,;
ldDate as Date, ;
llRet as Logical
are logicals, with value .F.

The 'as type': don't worry I don't have to type this myself, it's a fine routine in Thor doing this for you.
it serves the intellisense.


Mike,
Have now changed the code in such a way that in case 1 instead of 'clear events' I now have 'quit' and on the line above it a call to my clearing procedure.

Olaf,
Thanks for the sample, it does not work in my case since I have already in my vfpstart.prg a call to a procedure calling the 'on shutdown', to prevent a mistakenly click on the main close button instead of a click on the close button from e.g. a form or class.
Your idea is clear to me.

Regards,
Koen
 
Koen,

my idea of a Queryunload code taking into account ReleaseType does not depend on QUIT being used for ON SHUTDOWN. This is completely separate. This first part and code example about Quit wasn't even addressed to you.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top