A client wanted to protect sensitive information from prying eyes when the computer was left unattended. Its all very well to have access to certain areas of the application password protected. What happens when someone who has access privileges to sensitive information leaves his computer unattended? People would not only see this information but could conceivably have access to all restricted areas this access allowed.
So how do I monitor activity in the application and activate a locking mechanism either manually or automatically?
The answer: use a form's OnTimer, and OnKey events. First you will need to declare some variables to hold values. These can be declared in your Autoexec Script or using the method described in Dr. Waynes A Better Way to Initialize Global Variables.
DIM global last_form as c DIM global Scrn_chck_time as c DIM global Scrn_chck_time as c DIM global Scrn_chck_time2 as c DIM global Scrn_chck_diff as n DIM global Scrn_chck_val as n DIM global Scrn_chck_len as n
Now all forms need to be setup the following way. First the OnActivate and OnInit form events need to contain the following:
OPTION NOBREAK F=parentform.this 'This sets the start time to compare against the elapsed time. Scrn_chck_time=time() 'This variable will be used to store any keystroke activity on the form. Scrn_chck="" 'This variable will measure the number of characters in the 'Scrn_chck variable Scrn_chck_len=0 'This variable contains the total number of characters from the last 'keyboard activity and compare against any additional keyboard 'activity recorded. Scrn_chck_val=0 END
Next we need to monitor keyboard activity. The form's OnKey event needs to do the following:
option nobreak if between(a_user.key.value,"0","z") then 'if any alphanumeric keys are pressed a_user.key.handled=.T. if a_user.key.event="down" Scrn_chck=Scrn_chck + a_user.key.value 'store the keystrokes Scrn_chck_len=len(scrn_chck) 'measure the number of keystrokes. end if end if end
Now that we are recording our keyboard activity we need to check for any activity. First the form's Timer property needs to be set to 1 second.

Fig. 1. Set the form's Timer interval to 1 second.
The forms OnTimer event needs to do the following:
option nobreak
' gets the elapsed time to compare against the time recorded when the form was opened (ie. Scrn_chck_time)
scrn_chck_time2=time()
' converts time to seconds for subtraction
T_start=toseconds(Scrn_chck_time)
T_end=toseconds(scrn_chck_time2)
' subtracts the two times and gets the amount of time elapsed
scrn_chck_diff=t_end - t_start
' Checks to see if 10 minutes has elapsed (10 X 60 seconds=600 seconds)
'and if there was any keyboard activity. If the time is greater than 10
'minutes but there is keyboard activity then do nothing.
if scrn_chck_diff > 600 .and. Scrn_chck_val=Scrn_chck_len then
script_play("close_all_forms")
end if
'Next check to see if previous keyboard activity (Scrn_chck_val) matches
'new keyboard activity (Scrn_chck_len). If there is activity it resets
' Scrn_chck_val to the same value as Scrn_chck_len. This
' way if there is no new key board activity then they will both have the same
'value and trigger the first IF statement that checks for time and
'keyboard inactivity (ie. Scrn_chck_val=Scrn_chck_len)
if Scrn_chck_val <> Scrn_chck_len then
Scrn_chck_val=Scrn_chck_val + Scrn_chck_len
end if
'When the first IF statement evaluates to true the script close_all_forms executes.
if scrn_chck_diff > 600 .and. Scrn_chck_val=Scrn_chck_len then
script_play("close_all_forms")
end if
The script, close_all_forms, closes all open forms and loads the locking form. This script is not my creation but someone elses. I only added two lines:
last_form=a_form_current
and
form.view("frm_blank_Scrn")
When I saved the original script for future use I neglected to record the author's name. My apologies to him / her!
Script close_all_forms
dim formnme as c
dim count as n
dim formshort as c
dim result as c
dim type as c
dim p as p
dim frm as p
dim i as n
dim j as n
dim k as n
dim charcount as c
' This stores the name of the last form open to load later
last_form=a_form_current
charcount=""
for j=1 to 5
formnme=""
formnme=:A5.form_enum("")
if formnme <> "" then
while formnme <> ""
count=at("@",formnme,1)-1
formshort=":" + left(alltrim(formnme),count) + alltrim(charcount)
p=obj(formshort)
if is_object(p) then
type=p.class()
if type <> "form" then
goto skip
end if
p.close()
end if
skip:
formnme=:A5.form_enum(formnme)
end while
end if
charcount=alltrim(str(j-1))
next j
charcount=""
for k=1 to 5
formnme=""
formnme=:A5.browse_enum("")
if formnme <> "" then
while formnme <> ""
count=at("@",formnme,1)-1
formshort=":" + left(alltrim(formnme),count) + alltrim(charcount)
p=obj(formshort)
if is_object(p) THEN
type=p.class()
if type <> "browse"
goto skip2
end if
p.close()
end if
skip2:
formnme=:A5.browse_enum(formnme)
end while
end if
charcount=alltrim(str(k-1))
next k
' This opens the form which blanks the screen and locks the system.
form.view("frm_blank_Scrn")
end
The system can be manually locked, by placing a button on all your forms with the following code;
'Lock Button button
option nobreak
script_play("close_all_forms")
end
When form frm_blank_screen loads the user sees the following:
What locks the system is the form properties set for frm_blank_screen.
In the Form tab all the Restrictions should be checked and Hide status bar should be checked.
The Window tab should have Position=0 and Size=100. All boxes in Window Style should be unchecked.
The Menus / Toolbars should have View=<None>, View right click=<None>, and Toolbars View=<None>.
The Form's CanExit event should contain the following command to stop anyone from exiting the form;
Cancel()
The form's OnAcivate and OnInit events should contain the following;
option nobreak F=parentform.this :A5.Window_Title="Security Lock" 'With window sizing disabled in form properties the A5 window can be ' minimized and sized but not the form window. The form window will ' always be maximized in the A5 window. F.maximize() end
The form event OnKey should contain the following:
' the password scheme that follows was taken from
'Dr. Waynes book Xbasic for Everyoneoption nobreak
f=parentform.this
dim privileges as n
dim shared your_password as c
dim global Your_name as c
dim global status as c
dim advisor_new as c
dim tbl_name as c
dim shared a_db_current_path as c
' you need to trap the Escape key the first time it is used to
' avoid aborting the script and loading the last_form. Subsequent use
' of the Escape key will behave as it should.
if a_user.key.value="{ESC}" then
a_user.key.handled=.T.
end
end if
' you need to trap the F1 key because its a system key and
'will call up the Help screen rather than starting the script.
if a_user.key.value="{f1}" then
a_user.key.handled=.T.
end
end if
if a_user.key.value <> "{ESC}" then
a_user.key.handled=.T.
if a_user.key.event="down"
tbl_name=a_db_current_path+"users.dbf"
tries=0
start:
ui_beep()
if tries=3 then
goto fail
end if
your_password=ui_get_password("Authorization Required!","\
Please enter your password to Enter!","","*")
if your_password="" then
ui_beep()
ui_msg_box("No Password Entered!","\
Access denied!",+ui_stop_symbol)
tries=tries + 1
end
end if
if Your_password > "" then
your_password=encrypt(your_password)
privileges=lookupn("F",\
Your_password,"privileges",tbl_name,"password")
if privileges <2 then
ui_beep()
ui_msg_box("Authorization Denied!","\
Your Security clearance does not allow Access!",\
ui_stop_symbol)
tries=tries + 1
goto start
end if
end if
end if
end if
f.hide()
f.close()
' this loads the last form whose name was stored when
'the script Close_all_forms played
form.view(last_form)
end
fail:
tries=3
a5.close()
end
Some final points. If you like to have multiple forms loaded you will need to change that. My method only monitors activity in the current active form. Any forms running in the background will record no activity and lock the system.
Also, no provision has been made for mouse activity. I didnt feel it was necessary as a snoop would very likely be using the mouse to move around the application and would be locked out after 10 minutes. There is an article on this web page that emulates mouse rollovers and could possibly be adapted to monitor mouse activity if wanted.
As to the time limit before the screen locks it does not have to be hard coded. If you use Dr. Waynes method mentioned above to initialize variables you could allow the user to set a different time.
Instead of the following:
if scrn_chck_diff > 600 .and. Scrn_chck_val=Scrn_chck_len then
script_play("close_all_forms")
end if
You could use a numeric variable in place of a number.
if scrn_chck_diff > var->time_check .and.
Scrn_chck_val=Scrn_chck_len then
script_play("close_all_forms")
end if
| Editor's note: Robert has a clever idea to blank out a screen after
a defined period of inactivity. If you study his code carefully you may see
some ways to improve it. For example, I cannot see any reason to set the
OnTimer interval to 1 second and then check to see if 10 minutes have
elapsed. Why not just set the OnTimer interval to 600 seconds? I
also do not think it is necessary to record the number of keystrokes posted in
the 10-minute interval. Instead, create a global variable,
"keystroke_activity", and set it to true at the initiation of
the form. The OnKey event will also set "keystroke_activity"
to true. Then the OnTimer event script will check to see if
"keystroke_activity" is true. If it is true, the script will
set the variable to false and then exit. The next time around, if no
keystrokes have been recorded, the variable will still be false, and
when OnKey detects this fact, it will call the close_all_forms
script. Care to modify Robert's scripts? If you do, send them to me and I'll post them. |
9/7/02
Don't forget, we need your feedback to make this site better!