Code zu Fenstern und Formularen in Classic Visual Basic
- Überwachen des Aktivierens und Deaktivierens eines Formulars
- „Wiederherstellen“ von Fenstern
- Ermitteln, ob eine
InputBox
über Abbrechen geschlossen wurde - Abfrage beim Schließen eines Fensters über die Systemschaltfläche Schließen
- Schließen eines fremdes Fenster anhand seines Fenstertitels
- Deaktivieren von Alt+F4 zum Schließen von Fenstern
- Hinzufügen eines Fensterschattens unter Windows XP
- Beheben von Fokusproblemen bei Menüs für Symbole im Infobereich
- Verschieben eines Formulars mit der Maus
- Zentrieren eines Formulars
- Modales Anzeigen eines Formulars ohne
vbModal
- Entladen aller Formulare einer Anwendung
- Verhindern des Flackerns bei der Aktualisierung von Fenstern
- Entfernen von Einträgen aus dem Systemmenü
- Anzeigen eines Anwendungsfenster vor allen anderen Anwendungen
Überwachen des Aktivierens und Deaktivierens eines Formulars
Um mitzubekommen, wenn ein Formular den Eingabefokus erhält oder verliert, reichen die Ereignisse Activate
bzw. GotFocus
und LostFocus
nicht aus. Die im Folgenden angegebene, einfach zu implementierende Lösung bedient sich eines Timer-Steuerelements, das in regelmäßigen Abständen prüft, ob das Formular noch aktiv ist. Bei einer Statusänderung wird ein Pseudoereignis aufgerufen:
„Wiederherstellen“ von Fenstern
Die WindowState
-Eigenschaft von Formularen dient dazu, den Status eines Fensters zu ermitteln oder zu setzen. So kann man beispielsweise durch entsprechendes Setzen der Eigenschaft ein Fenster minimieren oder maximieren. Es geht jedoch eine Möglichkeit ab, das Fenster wiederherzustellen. Wird ein Fenster nämlich minimiert und will das Programm das Formular wieder einblenden, dann ist es unzureichend, die Eigenschaft WindowState
auf den Wert vbNormal
zu setzen. Dadurch würde das Fenster normal angezeigt, selbst wenn es vor dem Minimieren maximiert angezeigt wurde. Die im Folgenden angegebene Prozedur RestoreWindow
bewirkt, daß das Fenster in den letzten (nicht minimierten) Status zurückversetzt wird:
Der oben angeführte Ansatz nimmt allerdings recht viel Platz in Anspruch. Weiters ist diese Funktionalität ja bereits in Windows implementiert, was einen Aufruf in das Windows-API nahelegt: Die API-Funktion ShowWindow
in Verbindung mit der Konstanten SW_RESTORE
ist genau zu diesem Zweck geeignet:
Ermitteln, ob eine InputBox
über Abbrechen geschlossen wurde
Visual Basic stellt für Benutzereingaben eine vordefinierte Funktion InputBox
zur Verfügung, deren Rückgabewert die vom Benutzer eingegebene Zeichenfolge enthält. Das Eingabeformular enthält eine Schaltfläche, über die der Eingabevorgang abgebrochen werden kann. InputBox
stellt keine dokumentierte Möglichkeit bereit, herauszufinden, ob der Benutzer das Fenster durch Abbruch oder durch Bestätigung der Eingabe geschlossen hat. Diese Unterscheidung ist aber trotzdem über einen kleinen Trick mit der Funktion StrPtr
, die einen Zeiger auf ein String
-Objekt zurück gibt, möglich:
Abfrage beim Schließen eines Fensters über die Systemschaltfläche Schließen
Im Ereignis QueryUnload
eines Formulars kann der Grund für das Schließen des Formulars ermittelt werden. In einigen Fällen ist es sinnvoll, den Benutzer darauf hinzuweisen, daß er versucht, ein Formular zu schließen. Dies ist beispielsweise bei MDI-Formularen der Fall. Der folgende Beispielcode zeigt, wie der Benutzer zur Bestätigung des Vorgangs aufgefordert werden kann und wie bei negativer Antwort des Benutzers das Schließen des Formulars unterbunden werden kann:
Ein alternativer Einsatzzweck wäre, daß Benutzereingaben nach dem Schließen des Formulars nicht verloren gehen sollen. Das Fenster soll also nur ausgeblendet, nicht jedoch wirklich geschlossen werden. Zu diesem Zweck könnte man ähnlich vorgehen, wie dies im obenstehenden Code gezeigt wird, wobei über den Aufruf Call Me.Hide
bewirkt werden kann, daß das Formular nur versteckt und nicht entladen wird.
Der Wert der Variablen Cancel
ist in diesem Beispiel nicht von Bedeutung. Das Entladen des Formulars tritt nämlich nur ein, wenn Cancel
unverändert bleibt. Durch Negation wird unkompliziert der Wert der Variablen verändert.
Schließen eines fremdes Fenster anhand seines Fenstertitels
Folgender Code sucht nach einem Fenster mit einem bestimmten Titel und schließt dieses, wenn es geöffnet ist:
Deaktivieren von Alt+F4 zum Schließen von Fenstern
Das Schließen von Fenstern durch Drücken der Tastenkombination Alt+F4 kann mit Visual-Basic-eigenen Mitteln unterbunden werden. Dazu kann folgender Code einem Formular hinzugefügt werden, wobei die KeyPreview
-Eigenschaft des Formulars auf True
gesetzt sein muß:
Hinzufügen eines Fensterschattens unter Windows XP
Seit Windows XP können Fenster mit einem Schlagschatten ausgestattet werden. Dies ist bei Menüs standardmäßig der Fall, kann aber auch für eigene Fenster, nicht jedoch darauf plazierte Steuerelemente, aktiviert werden:
Beheben von Fokusproblemen bei Menüs für Symbole im Infobereich
Beispiele zum Hinzufügen eines Symbols in den Infobereich der Taskleiste gibt es im Web wie Sand am Meer. Anwendungen unter Windows können über die Funktion Shell_NotifyIcon
ein Symbol im Infobereich hinzufügen und manipulieren.
Einige der Beispiele, die man findet, demonstrieren auch die Verwendung von Kontextmenüs auf dem Symbol. Ein Großteil dieser Beispiele ist jedoch nicht unproblematisch und weist einen unschönen Nebeneffekt auf: Das über dem Symbol angezeigte Kontextmenü kann nicht mit der Tastatur bedient werden, so ist etwa das Schließen des Menüs durch Drücken der Esc-Taste nicht möglich.
Eine stabile Lösung, deren Implementierung besonders einfach ist und die unter Windows Me und Windows 2000 funktioniert, sieht wie folgt aus:
Dem Projekt wird ein Formular hinzugefügt und dieses beispielsweise
FDummy
genannt. Dieses Formular wird zur Lebenszeit der Anwendung nie sichtbar gemacht, es muß auch keine weitere Implementierung enthalten.Man erstellt ein Kontextmenü mit dem Menüeditor von Visual Basic und benennt es beispielsweise
mnuPopupNotifyIcon
, den Eintrag auf höchster EbenemnuPopup
.-
Weiters ist die Deklaration der Funktion
SetForegroundWindow
erforderlich: Anschließend fügt man dem Projekt den restlichen Code zur Verwaltung des Symbols im Infobereich hinzu.
-
Das Anzeigen des Kontextmenüs ist dann denkbar einfach:
Verschieben eines Formulars mit der Maus
Eine etwas unkonventionelle Art, dem Benutzer die Möglichkeit zu geben, ein Formular (oder ein beliebiges Steuerelement, das Mausereignisse empfängt) mit der Maus zu verschieben, ist mit reinen Bordmitteln von Visual Basic umsetzbar. Dazu wird die aktuelle Mausposition bei Drücken einer Maustaste gespeichert und der Verschiebungsmodus aktiviert. Bei Eintreten des MouseMove
-Ereignisses wird die aktuelle Position basierend auf der ursprünglichen Position des Formulars und der aktuellen Mausposition berechnet. Wird die Maustaste losgelassen, dann ist der Verschiebungsvorgang beendet:
Zentrieren eines Formulars
Manchmal ist es notwendig, ein Formular zu zentrieren, ohne seine StartUpPosition
einzustellen. Zu diesem Zweck kann die Methode Move
des Formulars mit entsprechenden Positionskoordinaten aufgerufen werden. Diese Methode arbeitet schneller als das getrennte Setzen der Eigenschaften Left
und Top
. Move
entspricht der API-Funktion MoveWindow
:
Modales Anzeigen eines Formulars ohne vbModal
Wenn man unter Visual Basic versucht, von einem modal angezeigten Formular (FOptions
) aus, ein nicht-modales Formular (FControl
) anzuzeigen, wird ein Fehler ausgelöst. Eine Lösung des Problems bietet folgender Code, bei dem zuerst das aufrufende Formular deaktiviert und anschließend das nicht-modale Formular angezeigt wird:
Weiters muß im Unload
-Ereignis von FControl
der nachfolgende Code hinzugefügt werden, um das Optionsformular wieder zu aktivieren:
Es ist zu beachten, daß diese Methode nicht den gleichen Effekt hat wie das herkömmliche modale Anzeigen von Formularen. Wird ein Formular modal angezeigt und man wählt sein Elternfenster in der Taskleiste, dann blinkt die Titelleiste des modalen Dialogs. Durch Deaktivieren des Elternfensters wird dieser hilfreiche visuelle Effekt unterbunden.
Entladen aller Formulare einer Anwendung
Die End
-Anweisung sollte nicht zum Beenden eines Programms verwendet werden, da dadurch nicht alle vom Programm belegten Speicherressourcen ordnungsgemäß freigegeben werden. End
verhindert nämlich, daß Code zum Aufräumen, also etwa das geordnete Schließen von Datenbankverbindungen und Dateien sowie zerstören von Objekten, ausgeführt wird. Anstelle dieses Befehls könnte man folgenden Code verwenden, der beispielsweise im Unload
-Ereignis des Hauptformulars abgelegt sein kann:
Wichtig ist, daß vor dem Entladen der Formulare alle aktiven Timer-Steuerelemente deaktiviert und Verweise auf andere Objekte wie etwa andere Formulare oder Klassen aufgelöst werden. Wenn die Verweise entfernt wurden, beendet sich die Anwendung von selbst.
Verhindern des Flackerns bei der Aktualisierung von Fenstern
Besonders bei größeren Formularen mit vielen Steuerelementen fällt es störend auf, daß die Steuerelemente bzw. das Formular während des Aktualisierens flackert. Folgender Code unterbindet während der Aktualisierung ein Neuzeichnen des Fensters, dessen Zugriffsnummer übergeben wird. Das Fenster wird erst dann neu gezeichnet, wenn die Prozedur UnlockWindow
aufgerufen wird:
Folgender Code wird an der Stelle, an der die Aktualisierung der Anzeige stattfinden soll, eingesetzt (statt Me.hWnd
kann auch die Zugriffsnummer eines anderen Fensters oder Steuerelements übergeben werden:
Von der Verwendung von LockWindowUpdate
zum Unterdrücken der Fensteraktualisierung während mehrerer Manipulationen wird abgeraten. Die vorzuziehende Methode wäre, die Funktion SendMessage
mit der Konstanten WM_SETREDRAW
und der Zugriffsnummer des Fensters, das nicht neu gezeichnet werden soll, zu senden. Dazu werden die folgenden Deklarationen benötigt:
Folgender Code wird an der Stelle, an der die Aktualisierung erfolgen soll, verwendet. Control
bezeichne im folgenden Code das Steuerelement, dessen Aktualisierung unterbunden werden soll:
Mit dieser Thematik beschäftigt sich auch der Artikel Gefrierschrank von Harald M. Genauck [MVP].
Entfernen von Einträgen aus dem Systemmenü
Über die Funktion DeleteMenu
lassen sich einzelne Menüeinträge aus dem Systemmenü (oder einem herkömmlichen Hauptmenü) eines Formulars entfernen. Die Funktion GetSystemMenu
dient dazu, die Zugriffsnummer des Systemmenüs eines Formulars zu ermitteln. Im folgenden Listing sind die entsprechenden Funktionsdeklarationen wiedergegeben:
Durch Übergabe der Konstante MF_BYPOSITION
im Parameter wFlags
wird festgelegt, daß der in nPosition
übergebene Wert die Ordnungszahl des Menüpunkts im Menü darstellt. Die Bedeutungen der Ordnungszahlen sind in folgender Übersicht angegeben:
Ordnungszahl | Bedeutung |
---|---|
0 | Wiederherstellen |
1 | Verschieben |
2 | Größe ändern |
3 | Minimieren |
4 | Maximieren |
5 | Trennlinie |
6 | Schließen |
Folgender Aufruf würde den Eintrag Maximieren aus dem Systemmenü eines Formulars entfernen:
Es gibt aber auch noch eine weitere Möglichkeit, den Schließen-Eintrag aus dem Systemmenü und die dazugehörige Systemschaltfläche aus der Titelleiste eines Formulars zu entfernen bzw. die Systemschaltfläche zu deaktivieren, die auf Aufrufen der Funktion RemoveMenu
basiert. Mit diesem Code wird zuerst geprüft, ob überhaupt noch Einträge zum Entfernen vorhanden sind. Nach dem Entfernen wird die Menüleiste neu gezeichnet:
Anstatt Menüeinträge anhand ihrer Position zu entfernen, empfiehlt es sich, bestimmte Menüeinträge anhand benannter Befehle mittels MF_BYCOMMAND
zu entfernen. Folgendes Beispiel zeigt die Vorgehensweise zum Entfernen des Menüeintrags und der Systemschaltfläche zum Minimieren eines Formulars (dies ist seit Visual Basic 5.0 über eine Formulareigenschaft möglich):
Anzeigen eines Anwendungsfenster vor allen anderen Anwendungen
Oft hört man die Frage, wie man es denn hinbekommt, das Fenster seiner Anwendung wirklich in den Vordergrund zu bringen, sodaß es über allen anderen Fenstern angezeigt wird. Die Funktionen SetActiveWindow
, BringWindowToFront
und noch einige andere Funktionen sind hierzu nicht ausreichend, über einen Aufruf dieser Funktionen kann lediglich erreicht werden, daß die Schaltflächen der Fenster in der Taskleiste blinken. Das Zauberwort heißt in diesem Fall SetWindowPos
.
Über einen kleinen Trick kann man es mit dieser API-Funktion erreichen, daß das Formular wirklich im Vordergrund erscheint, ohne lästig zu blinken und dauerhaft im Vordergrund zu sein. Der folgende Code muß in einem Formular abgelegt werden, auf dem ein Timer-Steuerelement mit dem Namen tmrSetOnTop
plaziert ist: