Jetzt stellt dies nicht wirklich ein Problem dar, denn üblicherweise genügt es, den Anwender zu informieren, das Programm für einen Updatevorgang zu beenden.
Dieser Gedankengang hat allerdings einen kleinen Haken, den Murphy sich nur zu gerne zu Nutzen macht. In einigen Fällen ist der Anwender, der eine Applikation sperrt, gerade nicht an seinem Arbeitsplatz...
Damit unsere Anwendung von sich aus feststellen kann, ob der Anwender eine 'Denkpause' eingelegt hat, benötigen wir eine systemweite Prüfung auf Aktivitäten bzw. in unserem Fall auf Inaktivitäten. Ist bspw. über einen Zeitraum von 15 Minuten keine Benutzereingabe erfolgt, dann können wir mit unserem Programm reagieren, und eine zeitgesteuerte Messagebox einblenden. Welche wiederum nach Ablauf ihres Timeouts ggf. das automatische und geordnete Beenden unserer Anwendung durchführen kann.
Im u.a. Beispiel wird mit einer PUBLIC Variablen gearbeitet. Alternativ kann das Objekt auch in einer Applikationsproperty erzeugt werden. Wichtig ist auf jeden Fall, dass der Timer jederzeit erreichbar ist.
Der Timer kann mit zwei Parametern versehen werden.
Parameter 1 definiert den Timeout Zeitraum in Minuten
Parameter 2 gibt den Timerzyklus in Sekunden vor
Wer die Parameter nicht nutzen möchte kann natürlich die entsprechenden Eigenschaften sozusagen 'ab Werk' vorbesetzen.
* // Funktionstext
CLEAR
PUBLIC goTimer as Timer
* // 1 minütiger Timeout mit 15 Sekunden Prüfinterval
* // Zum Beenden im Befehlsfenster 'Release goTimer' eingeben
goTimer = CREATEOBJECT( [InactivityTimer] , 1 , 15 )
* // Bemerkt Benutzeraktivitäten und feuert ein Ereignis, nachdem
* // der definierte Zeitraum für Inaktivität überschritten wurde.
DEFINE CLASS InactivityTimer as Timer
* // Deklaration der API Konstanten
#DEFINE WM_KEYUP 0x0101
#DEFINE WM_SYSKEYUP 0x0105
#DEFINE WM_MOUSEMOVE 0x0200
#DEFINE GWL_WNDPROC (-4)
* // Interne Eigenschaften setzen und Timer setzen (5Sek.)
_iTimeoutInMinutes = 0
_tLastActivity = {/:}
Interval = 5000
Enabled = .T.
* // Auf API Ereignisse horchen sobald die Form gestartet wurde
* // Optional wird ein Timeout Wert als Parameter übergeben
* // Zusätzlich kann als weiterer Parameter der Prüfinterval in
* // Sekunden übergeben werden.
PROCEDURE Init ( vTimeoutInMinutes as Integer , vIntervalInSeconds as Integer )
WITH This
._iTimeoutInMinutes = EVL( vTimeoutInMinutes , 1 )
.Interval = EVL( vIntervalInSeconds , 5 ) * 1000
._tLastActivity = DATETIME()
ENDWITH
BINDEVENT( 0 , WM_KEYUP , This , [WndProc] )
BINDEVENT( 0 , WM_SYSKEYUP , This , [WndProc] )
BINDEVENT( 0 , WM_MOUSEMOVE , This , [WndProc] )
ENDPROC
* // mit dem Lauschen aufhören
PROCEDURE Unload
UNBINDEVENTS( 0 , WM_KEYUP )
UNBINDEVENTS( 0 , WM_SYSKEYUP )
UNBINDEVENTS( 0 , WM_MOUSEMOVE )
ENDPROC
* // Jedes Ereignis zählt als Aktivität...
PROCEDURE WndProc ( hWnd as Long, Msg as Long, wParam as Long, lParam as Long )
This._tLastActivity = DATETIME()
ENDPROC
* // Letzte Aktivität mit Timeout abgleichen
PROCEDURE Timer
WITH This
LOCAL ltFireEvent as Datetime
ltFireEvent = ._tLastActivity + ( 60 * ._iTimeoutInMinutes )
IF DATETIME() >= ltFireEvent
.eventTimeout()
ENDIF
ENDWITH
ENDPROC
* // Diese Methode über BINDEVENT übersteuern oder enthaltenen
* // Code überschreiben...
* // Bspw. kann hier der Wert von iTimeoutInMinutes überschrie-
* // ben werden um einen mehrstufigen Timeout zu ermöglichen
PROCEDURE eventTimeout
MESSAGEBOX( [<<< TIMEOUT >>>] , 0 , [Inaktiv] )
ENDPROC
ENDDEFINE
Keine Kommentare:
Kommentar veröffentlichen