Subject Re: Form closing when idle
From Mustansir Ghor <mustan31@hotmail.com>
Date Sun, 16 May 2021 15:47:16 -0400
Newsgroups dbase.getting-started

Dear Mervyn Sir

Thank you so much.

Best Regards
Mustansir

Mervyn Bick Wrote:

> 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
>