>I want to halt an application when the user leaves it idle for 5 minutes. For screens I use the keypress() method to detect the keyboard activity and reset the timer. How do I detect the MOUSE activity? May be I should use ON KEY LABEL command?
>TIA
>Ed
Ed,
I got some tips from Jim Booth a while back about this. Let me pass them on as best as I can to you. I've had good success with them and use them is all my base form classes.
Let me provide a little backdrop.
First of all you need to know two things: 1) Am I in the middle of an edit? and 2) How do I trap for mouse movement?
With respect to #1 has the user started an edit session and gone to lunch, answered the phone or some other task that can cause an amount of inaction time.
With respect to #2 is the user moving the mouse for some reason? Perhaps they have another window open?
Ok, in each base form I would have some properties. You only need three for a really basic operation. I have more and I'll explain them afterwards. The three are:
IsEditActive - Self explanatory. Set & Check this in the appropriate spot.
MouseX - Mouse 'X' position
MouseY - Mouse 'Y' position - again, self explanatory
When you INIT ot ACTIVATE (my choice) your form use AMOUSEOBJ(TheInfo) to store the current mouse location. Remember to fisrt dimension this array before calling AMOUSEOBJ(). For some reason the array isn't created automatically. Here's the text about that from the help file - "If the array you specify doesn't exist, it isn't created." Go figure.
Element 3 & 4 of the array (TheInfo in this case) hold the X & Y mouse position. Check out the other options for further choises. Stash those into the form's MouseX & MouseY properties. That is all you need to do as far as the form goes for a simple solution.
Now... In the Timer Object that you place on this form you need, in the Timer Event to have a LOCAL copy of MouseX & MouseY. Dimension and call another AMOUSEOBJ() into another LOCAL array.
If both the form's MouseX & MouseY match the TImer Event's MouseX & MouseY values you KNOW the mouse has NOT MOVED, ergo no one' at the wheel. *g*
If, at this point, an edit is not active just call your form's Release method.
Now... A few pointers.
For a five (5) minute duration put into the Timer's Interval property the value of 300000. That would be 1000 * 5 * 60 in terms of milliseconds.
Make sure to check your form's IsAnEditActive property (whatever you name it) and proceed accordingly.
Consider putting the basic logic for all of this in a class baseform. Then you aren't reinventing the wheel every time.
I also add a few extra features that are still evolving. To give you a couple of ideas here are some I use:
UseFormExitTimer (property .T. or .F.) - Do I use the form't AutoExit feature at all? Some forms do not and I want a switch to turn it off & on.
UseDefaultTimerAmount (property .T. or .F.) - Do I use the Timer's default Interval amount?
DefaultIntervalAMount (property - Numeric) - Holds my project's default Timer Interval amount for ALL FORMS. This can be overridden on each form as needed.
If UseDefaultTimerAmount = .F. then I call a METHOD named
SETINTERVAL. Now this is a critical part of my development approach. In this method I have a
DEFAULT Timer Interval Amount that is a fail-safe, fallback position. That way I can just call the Method without worrying.
Also inside SETINTERVAL I have the following (It's a fair amount of code but it should help)
*
** Used to set Timer Interval based on Timer Scheme passed in.
** Default to DefaultInterval Property amount if no match or no parameter
*
LPARAMETERS SchemeToUse
IF VARTYPE(SchemeToUse) <> "C" OR EMPTY(SchemeToUse)
SchemeToUse = "DEFAULT"
ELSE
*
** A little defensive programming here
*
SchemeToUse = ALLTRIM(UPPER(SchemeToUse))
ENDIF
LOCAL nAmount
nAmount = THIS.DefaultInterval
DO CASE
CASE SchemeToUse = "DEFAULT"
*
** Default Timer Interval
*
nAmount = THIS.DefaultInterval
CASE SchemeToUse = "SCHEME1"
*
** Custome SCHEME 1
*
LOCAL nTIme
nTIme = (SECONDS() / 60 / 60)
DO CASE
CASE nTIme >= 0.00 AND nTIme <= 7.00
*
** Midnight to 7:00am
*
nAmount = 300000 && 5 Minutes
CASE nTIme > 7.00 AND nTIme <= 18.00
*
** 7.00.01 to 6:00pm
*
nAmount = 1800000 && 1/2 hour
CASE nTIme > 18.00 AND nTIme <= 20.00
*
** 6:00.01 to 8:00pm
*
nAmount = 600000 && 15 Minutes
CASE nTIme > 20.00 AND nTIme <= 24.00
*
** 8:00.01 to midnight
*
nAmount = 300000 && 5 Minutes
ENDCASE
CASE SchemeToUse = "SCHEME2"
*
** Custome SCHEME 2
*
CASE SchemeToUse = "SCHEME3"
*
** Custome SCHEME 3
*
CASE SchemeToUse = "SCHEME4"
*
** Custome SCHEME 4
*
CASE SchemeToUse = "SCHEME5"
*
** Custome SCHEME 5
*
CASE SchemeToUse = "SCHEME6"
*
** Custome SCHEME 6
*
CASE SchemeToUse = "5 MINUTES"
nAmount = 300000
CASE SchemeToUse = "10 MINUTES"
nAmount = 600000
CASE SchemeToUse = "15 MINUTES"
nAmount = 900000
CASE SchemeToUse = "20 MINUTES"
nAmount = 1200000
CASE SchemeToUse = "30 MINUTES"
nAmount = 1800000
CASE SchemeToUse = "45 MINUTES"
nAmount = 2700000
CASE SchemeToUse = "60 MINUTES"
nAmount = 3600000
OTHERWISE
ENDCASE
THIS.UpdateInterval(nAmount)
I then call
UpdateInterval from this method. Why? Well, I can also call it
directly any time I need to from any other code in the form or anywhere else. IOW, gives me a lot of control.
As you can see I have a few placeholders for future use. I'll just fill them in later as needed. I use
SCHEME1 at work since we want different Interval times depending on the time of day.
I also have a check for
IMMEDIATE EXIT which allows me to externally force everyone to log off. I need to be bel to control the app from many other events, time of day being just one. After around 9:00pm I just don't let people log on as I am starting to gear up for my nightly backup. This particular time will be the Server's time as that prevents the user from resetting their local clock. *g*
Anyway, that should give you a good start. Thanks again to Jim Booth for his help.
Best,
DD
Best,
DD
A man is no fool who gives up that which he cannot keep for that which he cannot lose.
Everything I don't understand must be easy!
The difficulty of any task is measured by the capacity of the agent performing the work.