Option Explicit
#If VBA7 Then
#If Win64 Then
Private Declare PtrSafe Function GetTickCount Lib "kernel32" Alias "GetTickCount64" () As LongPtr
#Else
Private Declare PtrSafe Function GetTickCount Lib "kernel32" () As LongPtr
#End If
Private Declare PtrSafe Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As LongPtr, ByVal hWnd2 As LongPtr, ByVal lpsz1 As String, ByVal lpsz2 As String) As LongPtr
Private Declare PtrSafe Function IsWindowVisible Lib "user32" (ByVal hwnd As LongPtr) As Long
Private Declare PtrSafe Function SetTimer Lib "user32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr, ByVal uElapse As Long, ByVal lpTimerFunc As LongPtr) As LongPtr
Private Declare PtrSafe Function KillTimer Lib "user32" (ByVal hwnd As LongPtr, ByVal nIDEvent As LongPtr) As Long
Private Declare PtrSafe Function SetProp Lib "user32" Alias "SetPropA" (ByVal hwnd As LongPtr, ByVal lpString As String, ByVal hData As LongPtr) As Long
Private Declare PtrSafe Function GetProp Lib "user32" Alias "GetPropA" (ByVal hwnd As LongPtr, ByVal lpString As String) As LongPtr
Private Declare PtrSafe Function RemoveProp Lib "user32" Alias "RemovePropA" (ByVal hwnd As LongPtr, ByVal lpString As String) As LongPtr
Private lStartTime As LongPtr, lTimerCountDown As LongPtr, lTimerProtect As LongPtr
#Else
Private Declare Function GetTickCount Lib "kernel32" () As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Declare Function IsWindowVisible Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Private Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long
Private Declare Function SetProp Lib "user32" Alias "SetPropA" (ByVal hwnd As Long, ByVal lpString As String, ByVal hData As Long) As Long
Private Declare Function GetProp Lib "user32" Alias "GetPropA" (ByVal hwnd As Long, ByVal lpString As String) As Long
Private Declare Function RemoveProp Lib "user32" Alias "RemovePropA" (ByVal hwnd As Long, ByVal lpString As String) As Long
Private lStartTime As Long, lTimerCountDown As Long, lTimerProtect As Long
#End If
Private lRemainingProtectDelay As Long, lUpdateProtectDelay As Long, lUpdateCountDown As Long
Private bEnteredEdit As Boolean
Private Const lCountDownInterval = 1 'Secs
Private Const lProtectDelay = 60 'Secs
'change constants to suit.
Private Const ASSESSMENT_SHEET = "Sheet1"
Private Const COUNT_DOWN_CELL = "B1"
Private Const SHEET_PASSWORD = "Password"
Public Sub Start()
If Not TimersAreSet Then
With Sheets(ASSESSMENT_SHEET)
.Unprotect Password:=SHEET_PASSWORD
.Range(COUNT_DOWN_CELL).NumberFormat = "mm:ss"
.Range(COUNT_DOWN_CELL).Value = 1 / (60 * 24) ' Start with 1 Minute
End With
Call StartTimers
End If
End Sub
Public Sub Finish()
Call StopTimers
End Sub
Private Sub StartTimers(Optional Dummy As Boolean)
bEnteredEdit = False
lUpdateCountDown = 0
lRemainingProtectDelay = lProtectDelay
lStartTime = GetTickCount
lTimerCountDown = SetTimer(0, 0, lCountDownInterval * 1000, AddressOf CountDown)
Call SetProp(Application.hwnd, "TimerCountDown", lTimerCountDown)
lTimerProtect = SetTimer(0, 0, &H7FFFFFFF, AddressOf Protectsheet)
Call SetProp(Application.hwnd, "TimerProtect", lTimerProtect)
End Sub
Private Sub StopTimers(Optional Dummy As Boolean)
Call KillTimer(0, GetProp(Application.hwnd, "TimerProtect"))
Call KillTimer(0, GetProp(Application.hwnd, "TimerCountDown"))
Call RemoveProp(Application.hwnd, "TimerProtect")
Call RemoveProp(Application.hwnd, "TimerCountDown")
lRemainingProtectDelay = 0
bEnteredEdit = False
lUpdateCountDown = 0
lStartTime = 0
End Sub
#If VBA7 Then
Private Sub CountDown(ByVal hwnd As LongPtr, ByVal uMsg As Long, ByVal nIDEvent As LongPtr, ByVal dwTimer As Long)
Dim hEdit As LongPtr
#Else
Private Sub CountDown(ByVal hwnd As Long, ByVal uMsg As Long, ByVal nIDEvent As Long, ByVal dwTimer As Long)
Dim hEdit As Long
#End If
On Error Resume Next
If bEnteredEdit = False Then
If (dwTimer - lStartTime) / 1000 > lRemainingProtectDelay Then
Call Protectsheet
Debug.Print "TimeOut"
Exit Sub
End If
End If
hEdit = FindWindowEx(Application.hwnd, 0, "XLDESK", vbNullString)
hEdit = FindWindowEx(hEdit, 0, "EXCEL6", vbNullString)
If IsWindowVisible(hEdit) Then
If bEnteredEdit = False Then
bEnteredEdit = True
End If
Else
lUpdateCountDown = lUpdateCountDown - lCountDownInterval
lUpdateProtectDelay = lProtectDelay + lUpdateCountDown
Debug.Print "remaining time : " & vbTab & lUpdateProtectDelay & vbTab & "Secs."
If bEnteredEdit Then
bEnteredEdit = False
lStartTime = GetTickCount
lRemainingProtectDelay = lUpdateProtectDelay
End If
End If
With Sheets(ASSESSMENT_SHEET).Range(COUNT_DOWN_CELL)
If CDate(.Value) > TimeSerial(0, 0, 0) Then
.Value = .Value - TimeSerial(0, 0, lCountDownInterval)
Else
Call Protectsheet
Debug.Print "Cell value reached 0."
End If
End With
End Sub
Private Sub Protectsheet(Optional Dummy As Boolean)
Call Sheets(ASSESSMENT_SHEET).Protect(Password:=SHEET_PASSWORD)
Call StopTimers
MsgBox "Time Out."
End Sub
Private Function TimersAreSet() As Boolean
TimersAreSet = CBool(lRemainingProtectDelay)
End Function
Private Sub Auto_Close()
Call StopTimers
End Sub