Diese Seite wurde zuletzt aktualisiert am 03.09.1999
Aktuell im ABOUT Visual Basic-MagazinGrundlagenwissen und TechnologienKnow How, Tipps und Tricks rund um Visual BasicAddIns für die Visual Basic-IDE und die VBA-IDEVBA-Programmierung in MS-Office und anderen AnwendungenScripting-Praxis für IE, Windows Scripting Host und das Scripting-ControlTools, Komponenten und Dienstleistungen des MarktesRessourcen für Programmierer (Bücher, Job-Börse)Dies&Das...

Themen und Stichwörter im ABOUT Visual Basic-Magazin
Code, Beispiele, Komponenten, Tools im Überblick, Shareware, Freeware
Ihre Service-Seite, Termine, Job-Börse
Melden Sie sich an, um in den vollen Genuss des ABOUT Visual Basic-Magazins zu kommen!
Informationen zur AVB-Web-Site, Kontakt und Impressum

Zurück...

Zurück...

(-hg) mailto:hg_waitcursor@aboutvb.de

Vergessen auch Sie immer wieder, bei länger andauernden Operationen den Sanduhr-Mauszeiger einzuschalten? Dabei ist sonst kaum ein anwenderfreundliches Feature so einfach wie dieses zu realisieren:

Screen.MousePointer = vbHourglass

Das war's schon, oder? Nein, natürlich nicht - Sie dürfen nicht vergessen, den Mauszeiger wieder zurück zu setzen. Sonst starrt der Anwender auf Ihre Anwendung und wartet und wartet, weil er glaubt, er dürfe noch nicht weiter arbeiten. Und wenn er nicht gestorben ist, dann wartet er noch heute...

Also noch ein

Screen.MousePointer = vbDefault

an das Ende des zeitaufwändigen Abschnitts platziert. Das war's jetzt aber wirklich, oder? Nein, immer noch nicht ganz. Das heißt, das war's, wenn es aus dem betreffenden Abschnitt keine Neben- und Hintertüren, sprich Anweisungen wie Exit Sub und dergleichen gibt. Falls doch, muss auch vor diesen Ausgängen der Mauszeiger zurückgesetzt werden. Und das vergisst man doch hin und wieder mal (Fehlerbehandlungen haben sich als die tückischsten Mauszeiger-Konservatoren bewährt)...


Die Sanduhr einschalten und vergessen?

Es geht bequemer und narrensicherer - mit genau zwei Anweisungen und keiner einzigen mehr. Voraussetzung ist allerdings, dass Sie die im folgenden vorgestellte Klasse clsWaitCursor in Ihr Projekt laden. Schauen Sie mal:

Sub Irgendwas()
  Dim nWaitCursor As New clsWaitCursor

  nWaitCursor
' ...jede Menge zeitaufwändige Operationen
End Sub

Nanu? Die Objekt-Variable mit As New dimensioniert und dann einfach nur einmal dahin geschrieben? Das soll funktionieren?

Jawohl. Wir haben es hier mit einem der seltenen Fälle zu tun, in denen die Dimensionierung mit As New ihren Zweck genau ihrer Funktionsweise entsprechend erfüllt. Wie Sie vielleicht wissen, erspart eine so erfolgende Dimensionierung die sonst notwendige ausdrückliche Zuweisung einer neuen Klasseninstanz an die Objekt-Variable:

Set nWaitCursor = New clsWaitCursor

Immerhin würde dies eine Zeile Code mehr bedeuten - Mensch, was sind wir heute wieder faul...!

Scherz beiseite - die Dimensionierung mit As New bedeutet, dass bereits eine Instanz der Klasse vorbereitet und der Objekt-Variablen zugewiesen wird. Allerdings wird die Instanz noch nicht real geladen. Das können Sie daran erkennen, dass hierbei noch nicht deren Initialize-Ereignis ausgelöst wird. Erst beim ersten Zugriff auf eine Eigenschaft oder eine Methode beginnt die Instanz richtig zu leben. Erfolgt jedoch während der Lebensdauer der Objekt-Variablen (Existenz im aktuellen Gültigkeitsbereich, hier innerhalb einer Prozedur) kein Zugriff, wird die Instanz nicht wirklich zum Leben erweckt. Merke: Die Lebensdauer einer Objekt-Variablen und die tatsächliche Lebensdauer einer Objekt-Instanz sind prinzipiell zwei verschiedene Dinge! Nebenbei bemerkt: Die ausbleibende Aktivierung einer Objekt-Instanz kann unter Umständen einen Performance-Gewinn bringen, wenn es sich etwa um ein aufwändiges Objekt mit langwierigen Initialisierungsoperationen, wie Datenbankverbindung aufnehmen und dergleichen, handeln sollte (wobei natürlich die Sanduhr angezeigt werden sollte... na, beißt sich jetzt etwa die Katze in den Schwanz, oder schiebt sich der Schwanz der Katze zwischen die Zähne?).

Und was hat es jetzt mit dieser merkwürdigen Code-Zeile auf sich, in der lediglich die Objekt-Variable sozusagen nackt herumsteht, ohne offensichtlichen Zugriff auf das Objekt über eine Eigenschaft oder einen Methodenaufruf?

Vielleicht erinnern Sie sich daran, dass bei Klassen genau eine Eigenschaft oder eine Methode (ja, doch, für Methoden gilt das auch!) als sogenannte Voreinstellung festgelegt werden kann. Das können Sie in den Prozedur-Attributen (Menü Extras) im Feld Prozedur-ID einstellen. Diese Voreinstellung bedeutet nichts weiter, als dass die betreffende Eigenschaft sozusagen gleich dem Objekt wird. Im Prinzip dürften Sie das auch von einigen Steuerelementen her kennen, etwa von der Textbox. Bei dieser können Sie auf die Angabe der Text-Eigenschaft verzichten, um auf deren Inhalt zuzugreifen:

Inhalt = Text1

anstelle von:

Inhalt = Text1.Text

Nun, da Sie genauso gut eine Methode als Voreinstellung festlegen können, kommt eben die besagte Code-Zeile dabei heraus. Beim Aufruf der hier als Voreinstellung festgelegten Methode Show der Klasse clsWaitCursor (der keine Parameter übergeben werden) sieht das dann so aus:

nWaitCursor

- und nichts weiter.

Dieser ein wenig hinterlistig erscheinende Aufruf der Show-Methode ist aber auch genau das, was die Objekt-Instanz nun braucht, um zum Leben erweckt zu werden. Gehen Sie den Code ruhig einmal Schritt für Schritt im Debug-Modus durch. Sie werden sehen, dass zunächst und allererst das Class_Initialize-Ereignis aufgerufen wird, worin einfach sicherheitshalber eine private Klassen-Variable mit dem Mauszeiger-Standardwert belegt wird (eigentlich ist das überflüssig, da die Konstante vbDefault auch nur den Wert 0 hat - aber wer weiß, vielleicht ändert sich das ja irgendwann mal):

Private Sub Class_Initialize()
  mPrevMousePointer = vbDefault
End Sub

Danach erst erfolgt der eigentliche Aufruf der Show-Methode:

Public Sub Show()
  With Screen
    mPrevMousePointer = .MousePointer
    .MousePointer = vbHourglass
  End With
End Sub

Hier wird der aktuelle Screen-MousePointer in mPrevMousePointer in Verwahrung gegeben und auf die Sanduhr umgestellt.

Sie fragen sich, wie die Sanduhr nun wieder abgestellt wird? Schließlich haben wir ja die beiden versprochenen Code-Zeilen bereits mit der Dimensionierung und dem geheimnisvollen Show-Aufruf verbraucht. Keine Bange, die Instanz der Klasse clsWaitCursor eliminiert sich ganz von alleine: Da die Objekt-Variable nWaitCursor nur in der Prozedur gültig ist, wird sie automatisch von Visual Basic beim Verlassen der Prozedur eliminiert. Das bedeutet, dass dadurch das Class_Terminate-Ereignis ausgelöst wird. Und genau dort wird der Mauszeiger wieder auf den in mPrevMousePointer aufbewahrten Wert zurückgestellt. Dies ist der eigentliche und ganze Trick bei der Sache.

Private Sub Class_Terminate()
  Screen.MousePointer = mPrevMousePointer
End Sub

Wie in der Überschrift versprochen: Sie brauchen die Sanduhr bloß einzuschalten und können sie dann getrost vergessen - egal, wann, wo, wie und warum Sie die Prozedur verlassen.

Wollen Sie die Sanduhr jedoch vorzeitig wieder abstellen, setzen Sie einfach nWaitCursor = Nothing. VB eliminiert daraufhin diese Instanz, löst das Terminate-Ereignis aus und bereitet eine neue Instanz vor, als ob die Objekt-Variable erneut mit As New dimensioniert werden würde. Und diese neue Sanduhr in Wartestellung können Sie jederzeit in der gleichen Prozedur wiederum einschalten - mit jenem verdeckten Aufruf der Show-Methode.


Klasse clsWaitCursor und Beispiel-Projekt (waitcurs.zip - ca. 4 KB)



Komponenten-Übersicht

Zum Seitenanfang

Copyright © 1999 - 2023 Harald M. Genauck, ip-pro gmbh  /  Impressum

Zum Seitenanfang

Zurück...

Zurück...