| Subject |
Re: Form closing when idle |
| From |
Mervyn Bick <invalid@invalid.invalid> |
| Date |
Sun, 16 May 2021 15:21:03 +0200 |
| Newsgroups |
dbase.getting-started |
| Attachment(s) |
close_on_idle.wfm |
On 2021/05/13 18:33, Mustansir Ghor wrote:
> Dear Mervyn sir
>
> I had read in this newsgroup, where there is routine that closes the form when it stays idle for certain time. Sir can you help me to recollect where I could find this routine.
My apologies for taking so long to respond. A little example form is
attached. This form uses the CALLBACK command so it will only work with
dBASE Plus 8 and later.
The example uses a keyboard hook and a mouse hook to monitor all
instructions to the form. Any keystroke or mouse movement resets the
timer. The idle time before the form closes is set to 2 minutes in the
example. You can obviously set it to your own requirements.
One minute before the form closes a warning count-down is displayed.
The keyboard and mouse hooks are completely stable provided they are
properly detached when the form is closed correctly.
There is one very annoying problem when one uses a keyboard or mouse
hook in a form. Any error, not necessarily in regard to the hook,
causes dBASE to crash and close. This is because the hook in Windows is
not detached when dBASE opens the form in the sourcecode editor.
The work-around is to disable both the timer and the hooks while the
form is being developed. The places to do this are marked in the form's
onOpen event handler.
Once you are certain that the form has no problems and is ready to be
used make the timer active and uncomment the line that attaches the hooks.
Mervyn.
| clear
#include winuser.h
#define wm_mousewheel 0x020A //not in winuser.h
** END HEADER -- do not remove this line
//
// Generated on 2021-05-13
//
parameter bModal
local f
f = new close_on_idleForm()
if (bModal)
f.mdi = false // ensure not MDI
f.readModal()
else
f.open()
endif
class close_on_idleForm of FORM
with (this)
onMouseOver = class::FORM_ONMOUSEOVER
onMouseOut = class::FORM_ONMOUSEOUT
onOpen = class::FORM_ONOPEN
onClose = class::FORM_ONCLOSE
height = 18.4545
left = 25.5714
top = 1.4091
width = 62.4286
text = ""
endwith
this.ENTRYFIELD1 = new ENTRYFIELD(this)
with (this.ENTRYFIELD1)
height = 1.0
left = 12.0
top = 5.7273
width = 25.7143
value = "Entryfield1"
endwith
this.TEXTLABEL1 = new TEXTLABEL(this)
with (this.TEXTLABEL1)
height = 1.0
left = 28.1429
top = 0.8636
width = 29.5714
text = ""
endwith
this.ENTRYFIELD2 = new ENTRYFIELD(this)
with (this.ENTRYFIELD2)
height = 1.0
left = 12.0
top = 8.7273
width = 25.7143
value = "Entryfield2"
endwith
function attach
if this.mhookProc == null
CALLBACK CLONG MouseHookWndProc(CINT, CUINT, CUINT) OBJECT this
this.mhookProc = GetCallAddress(class::MouseHookWndProc)
endif
mhInst = GetWindowLong(int(form.hwnd), WH_MOUSE)
this.mhook = SetWindowsHookEx(WH_MOUSE, this.mhookProc,mhInst, GetCurrentThreadId())
if this.khookProc == null
CALLBACK CLONG KeyHookWndProc(CINT, CUINT, CUINT) OBJECT this
this.khookProc = GetCallAddress(class::KeyHookWndProc)
endif
khInst = GetWindowLong(int(form.hwnd), WH_KEYBOARD)
this.khook = SetWindowsHookEx(WH_KEYBOARD, this.khookProc,khInst, GetCurrentThreadId())
return
function detach
UnhookWindowsHookEx(this.mhook)
UnhookWindowsHookEx(this.khook)
return
function form_onClose()
class::detach()
this.timer.enabled = false
return
function form_onMouseOut(flags, col, row)
form.mouseOver = false
return
function form_onMouseOver(flags, col, row)
form.mouseOver = true
return
function form_onOpen()
if type("GetCurrentThreadId") # "FP"
extern CULONG GetCurrentThreadId() kernel32 from "GetCurrentThreadId"
endif
if type("GetWindowLong") # "FP"
extern CLONG GetWindowLong(CHANDLE, CINT) user32 from "GetWindowLongA"
endif
if type("SetWindowsHookEx") # "FP"
extern CLONG SetWindowsHookEx(CINT, CPTR, CHANDLE, CULONG) user32 from "SetWindowsHookExA"
endif
if type("UnhookWindowsHookEx") # "FP"
extern CLOGICAL UnhookWindowsHookEx(CHANDLE) user32
endif
if type("CallNextHookEx") # "FP"
extern CLONG CallNextHookEx(CHANDLE, CINT, CUINT, CUINT) user32
endif
form.mouseOver = true
this.timer = new Timer( )
this.timer.parent = this
this.timer.seconds = seconds()
this.timer.allow_idle_time = 60 *2 // 2 minutes. value in sconds
this.timer.onTimer := this.check_action
this.timer.interval = 1
this.timer.enabled = true // set false while developing form ********
this.mhook = null
this.khook = null
this.mhookProc = null
this.khookProc = null
class::attach() // comment out while developing form *********
return
function check_action
if int(abs(seconds()-this.allow_idle_time-this.seconds)+1) < 61
this.parent.textlabel1.visible = true
else
this.parent.textlabel1.visible = false
endif
this.parent.textlabel1.text = 'This form will close in '+int(abs(seconds()-this.allow_idle_time-this.seconds)+1)+' second'+iif(int(abs(seconds()-this.allow_idle_time-this.seconds)+1) = 1,'', 's')
if seconds()-this.allow_idle_time-this.seconds >1
this.parent.close()
endif
return
function MouseHookWndProc(hCode, wParam, lParam)
if hCode = 0 and form.mouseOver = true
if wparam = wm_mousemove or ;
wparam = wm_nclbuttondown or ;
wparam = wm_lbuttondown or ;
wparam = wm_rbuttondown or ;
wparam = wm_mbuttondown or ;
wparam = wm_mousewheel
form.timer.seconds = seconds()
endif
endif
return CallNextHookEx(this.mhook, hCode, wParam, lParam)
function KeyHookWndproc(hCode, wParam, lParam)
t1 = wParam // virtual key code.
t2 = lParam // bit 31 = 0 keydown, bit 31 = 1 keyup
if bitset(lparam,31) = false and hCode = 0 and form.mouseOver = true
form.timer.seconds = seconds()
endif
return CallNextHookEx(this.khook, hCode, wParam, lParam)
endclass
|
|