[AccessD] brain fart

Drew Wutka DWUTKA at Marlow.com
Tue Oct 6 10:36:21 CDT 2009


I posted a solution a while back in Access 97.  It'll work in Access
2000 and later, with one quirk.  The solution William posts, requires a
constant checking of the object with focus.  That's all well and good,
but what if someone is reading through a report....no focus would
change.  Or what if someone was entering a lot of data in one field?

My solution hooks into the mouse and keyboard events of the OS, for the
Access thread itself.  So when something is done (mouse moves, keyboard
typed), the 'last activity' date variable is reset.  Callbacks are very
low over head, so this shouldn't be any more or less of an overhead hit
then a control timer. 

Here's how to do this:  Create a module (modMouseAndKeyboardCallbacks)

Paste the following code in there:

Option Compare Database
Option Explicit
Public gblCurrentKBHookID As Long
Public gblCurrentMouseHookID As Long
Public gblLastActivityTime As Date
Private Declare Function CallNextHookEx Lib "user32" (ByVal hHook As
Long, ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long
Private Type POINTAPI
    x As Long
    y As Long
End Type
Private Type MOUSEHOOKSTRUCT
    pt As POINTAPI
    hwnd As Long
    wHitTestCode As Long
    dwExtraInfo As Long
End Type
Function MouseCallbackProc(ByVal intCode As Integer, ByVal wParam As
Long, lParam As MOUSEHOOKSTRUCT) As Long
MouseCallbackProc = CallNextHookEx(gblCurrentMouseHookID, intCode,
wParam, lParam)
gblLastActivityTime = Now
End Function
Function KeyboardCallbackProc(ByVal intCode As Integer, ByVal wParam As
Long, lParam As Long) As Long
KeyboardCallbackProc = CallNextHookEx(gblCurrentKBHookID, intCode,
wParam, lParam)
gblLastActivityTime = Now
End Function

Now you have your callback procedures.  To use this, here's what is on
my sample form (which uses a timer (firing every second, but you could
change that to much higher for timeouts over a minute)) and a label
(lblInactivity):

Option Compare Database
Option Explicit
Private Const WH_KEYBOARD = 2
Private Const WH_MOUSE = 7
Private Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook
As Long) As Long
Private Declare Function SetWindowsHookEx Lib "user32" Alias
"SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal
hmod As Long, ByVal dwThreadId As Long) As Long
Private Declare Function GetCurrentThreadId Lib "kernel32" () As Long
Private Sub Form_Load()
gblCurrentMouseHookID = SetWindowsHookEx(WH_MOUSE, AddressOf
MouseCallbackProc, 0, GetCurrentThreadId)
gblCurrentKBHookID = SetWindowsHookEx(WH_KEYBOARD, AddressOf
KeyboardCallbackProc, 0, GetCurrentThreadId)
End Sub

Private Sub Form_Timer()
Me.lblInactivity.Caption = "Inactivity Timer: " & Format(Now -
gblLastActivityTime, "HH:MM:SS")
End Sub

Private Sub Form_Unload(Cancel As Integer)
UnhookWindowsHookEx gblCurrentMouseHookID
UnhookWindowsHookEx gblCurrentKBHookID
End Sub

The form load events launch the 'hooks'.  The unload events release the
hooks.  And the form's timer event simply displays the current time
(gblLastActivityTime) variation from 'Now()'.  So if you just sit and
watch it, it will count up the seconds (and minutes).  Move your mouse,
or use your keyboard, and the timer resets to 0's.  Just replace the
timer event with the specified amount of time you want to allow for
inactivity (with a docmd.Quit).  Have this form launched (and hidden)
when your database opens, and whalla, you're done.

Now for the quirk.  Callbacks require the 'AddressOf' command.  In
Access 97, there was no native command for this.  Someone had come up
with a module that performed the AddressOf function (I think it was Ken
Getz...), so you could use callbacks in Access 97 with the help of this
module.  With the advent of Access 2000, however, it began using VBA 6
(subset of VB 6), which did have a native AddressOf function (this
function returns a pointer to a public function, which an Operating
System process could then use to 'call' a function in one of your
programs (such as alerting your program to when a mouse or keyboard
event occurred).  The quirk is, that since VBA is an interpreted
language, IF you have opened the VBE, and the callback is running,
Access will lock up.  So as long as you don't try to view, or edit code,
it will work fine.  (Since users shouldn't be doing this, callbacks can
be used in a production database, they just need to be disabled when
developing the database, to prevent them from locking up Access).

So I would just put something in, that allows you to prevent that
Inactivity 'form' from opening when you need to go in and look at code.
As long as you do that, the 'bug' won't affect you, and your end users
get the benefits of callback functions! 

Drew

-----Original Message-----
From: accessd-bounces at databaseadvisors.com
[mailto:accessd-bounces at databaseadvisors.com] On Behalf Of Rocky Smolin
Sent: Saturday, October 03, 2009 10:08 AM
To: 'Access Developers discussion and problem solving'
Subject: [AccessD] brain fart

Dear List:

I need to terminate an mdb if there has been no activity for a specified
number of minutes.  I remember there was a thread about this recently
but can't remember the subject so I can search the archives.  Does
anyone remember that?

MTIA

Rocky

 

The information contained in this transmission is intended only for the person or entity 
to which it is addressed and may contain II-VI Proprietary and/or II-VI Business 
Sensitive material. If you are not the intended recipient, please contact the sender 
immediately and destroy the material in its entirety, whether electronic or hard copy. 
You are notified that any review, retransmission, copying, disclosure, dissemination, 
or other use of, or taking of any action in reliance upon this information by persons 
or entities other than the intended recipient is prohibited.





More information about the AccessD mailing list