Mittels der API-Funktion Sleep
können Sie die Ausführung einer Anwendung vorübergehend anhalten.
Sie rufen die Funktion einfach auf und übergeben die gewünschte
Anhaltezeit in Millisekunden. Der auf den Aufruf folgende Code wird
erst weiter abgearbeitet, wenn der Aufruf nach der angegebenen Zeit
zurückgekehrt ist.
Die Deklaration:
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMS As Long)
Ihre Anwendung soll beispielsweise 10 Sekunden
"schlafen":
Sleep 10000
Allerdings ist das Anhalten bzw. "Schlafen" wörtlich
zu verstehen - in der Anwendung geht nichts mehr, aber auch gar
nichts mehr. Und wenn zwischenzeitlich ein Fenster einer anderen
Anwendung ein Form der schlafenden Anwendung überdeckt hat und vor
deren Aufwachen wieder verschwindet, wird die Darstellung des
schlafenden Forms nicht aktualisiert. Sonderlich schön sieht das
nicht aus.
Abhilfe schafft die Maßnahme, den Aufruf der API-Funktion in
einen eigenen Thread zu legen. Die Anwendung selbst schläft dann
weiterhin, was das Ausführen von Code in der Anwendung angeht.
Aktualisierungen der Oberfläche, soweit sie eigenständig von
Windows und nicht wiederum durch Code Ihrer Anwendung durchgeführt
werden, erfolgen dennoch. Der einfachste Weg, einen separaten Thread
zu erzeugen, ist in Visual Basic der Einsatz einer
ActiveX-EXE-Komponente.
Diese ActiveX-EXE-Komponente namens "Sleeper" ist
denkbar schlicht gehalten. Sie besteht aus der einzigen Klasse
namens Sleep mit einer einzigen Methode - der Methode Action - und
der Deklaration der API-Funktion in der Klasse.
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMS As Long)
Public Sub Action(ByVal mSec As Long)
Sleep mSec
End Sub
Sie binden einen Verweis auf die kompilierte Sleeper-Komponente
in Ihre Anwendung ein. Der Methode Action übergeben Sie nun in
Millisekunden die gewünschte Verzögerungszeit:
Dim nSleep As New Sleep
nSleep.Action 10000 ' 10 Sekunden
Wenn Sie in den Prozedurattributen (Sie finden den Dialog dazu im
Menü "Extras") die Prozedur-ID auf
"(Voreinstellung)" setzen, können Sie den Methoden-Namen
auch weglassen:
Dim nSleep As New Sleep
nSleep 10000 ' 10 Sekunden
Die Sleeper-Komponente können Sie ohne Unterschiede
gleichermaßen in Visual Basic 5 und 6
kompilieren.
Wenn allerdings der Anwender bei längeren Verzögerungszeiten,
wie etwa 10 Sekunden, weiter in der Anwendung
herumklickt, wird früher oder später eine OLE-Meldung ausgegeben,
die etwas verwirrend vom Wechseln der Anwendung und ähnlichem
spricht. Da diese Meldung hier nur stört und ihr eigentlicher Sinn
hier auch nicht gegeben ist, können Sie sie auch unterdrücken.
Dies erfolgt auf der Seite der aufrufenden Anwendung. Setzen Sie
dazu in den Ole...-Eigenschaften des App-Objekts die
Eigenschaften OleRequestPendingTimeout und OleServerBusyTimeout auf
eine Zeit, die um einiges länger als die Verzögerungszeit ist,
etwa das dreifache. Dazu setzen Sie die Eigenschaft
OleServerBusyRaiseError auf True, um die Meldung als Fehlermeldung
an Ihre Anwendung umzuleiten. Diese Fehlermeldung können Sie dann
mittels der Anweisung On Error Resume Next vorsorglich ignorieren.
Da diese kleine Ole-Trickserei den Sleep-Aufruf um einiges
aufwändiger macht, packen wir dies alles in eine Hilfsprozedur in
einem Standard-Modul, das in die aufrufende Anwendung aufgenommen
wird.
Der Hilfsprozedur, die der Einfachheit halber ebenfalls Sleep
heißt, übergeben Sie wieder die gewünschte Verzögerungszeit in
Millisekunden, und optional, ob Sie die Ole-Meldungen tatsächlich
unterdrücken wollen (Voreinstellung ist True).
Die Funktion sorgt dafür, dass die alten Ole...-Einstellungen
des App-Objekts anschließend wieder in den beim Aufruf
angetroffenen Zustand zurück versetzt werden. Außerdem setzt sie
die TimeOut-Eigenschaften automatisch auf einen 3-fachen Wert der
gewünschten Verzögerungszeit, bzw. maximal auf den größten Wert
des Long-Wertebereichs.
Public Sub Sleep(ByVal mSec As Long, _
Optional ByVal NoTimeOutMessage As Boolean = True)
Dim nTimeOut As Long
Dim nOldBusyTimeOut As Long
Dim nOldPendingTimeOut As Long
Dim nOldBusyRaiseError As Boolean
Dim nSleep As New Sleep
If NoTimeOutMessage Then
On Error Resume Next
nTimeOut = 3 * mSec
If Err.Number Then
nTimeOut = 2147483647
Err.Clear
End If
With App
nOldPendingTimeOut = .OleRequestPendingTimeout
.OleRequestPendingTimeout = nTimeOut
nOldBusyRaiseError = .OleServerBusyRaiseError
.OleServerBusyRaiseError = True
nOldBusyTimeOut = .OleServerBusyTimeout
.OleServerBusyTimeout = nTimeOut
nSleep mSec
.OleRequestPendingTimeout = nOldPendingTimeOut
.OleServerBusyRaiseError = nOldBusyRaiseError
.OleServerBusyTimeout = nOldBusyTimeOut
End With
Else
nSleep mSec
End If
End Sub
Da das erstmalige Laden einer ActiveX-EXE immer ein wenig Zeit
benötigt, und da diese Zeit unter Umständen um einiges länger als
der gewünschten Verzögerungszeitraum sein kann, sollten Sie die
ActiveX-EXE vorab zum Laden zwingen, indem Sie die Funktion
irgendwann zuvor einmal mit der Verzögerungszeit von einer
Millisekunde und mit auf False gesetztem Parameter NoTimeOutMessage
aufrufen. Die ActiveX-EXE bleibt dann während der gesamten Laufzeit
Ihrer Anwendung im Arbeitsspeicher vorgehalten (den Windows
allerdings nach wie vor auslagern kann).
|