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:
Private Declare Function GetActiveWindow Lib "user32.dll" ( _
) As Long
Private m_FormFocus As Boolean
Private Sub Form_Load()
With Me.Timer1
.Interval = 20
.Enabled = True
End With
End Sub
Private Sub Timer1_Timer()
If GetActiveWindow = Me.hWnd Then
If Not m_FormFocus Then
m_FormFocus = True
Call Form_StateChanged(m_FormFocus)
End If
Else
If m_FormFocus Then
m_FormFocus = False
Call Form_StateChanged(m_FormFocus)
End If
End If
End Sub
Private Sub Form_StateChanged(ByVal Activated As Boolean)
Debug.Print _
IIf( _
Activated, _
"The window got active", _
"The window got inactive" _
)
End Sub
„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:
' Letzter nicht minimierter Status ("Normal" oder "Maximiert").
Private m_LastState As FormWindowStateConstants
Private Sub Form_Resize()
' Wenn der neue Status nicht "Minimiert" ist, Status als letzten
' nicht minimierten Status speichern.
If _
Me.WindowState <> vbMinimized And _
Me.WindowState <> m_LastState _
Then
m_LastState = Me.WindowState
End If
End Sub
Private Sub RestoreWindow()
If Me.WindowState = vbMinimized Then
Me.WindowState = m_LastState
End If
End Sub
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:
Private Declare Function ShowWindow Lib "user32.dll" ( _
ByVal hWnd As Long, _
ByVal nCmdShow As Long _
) As Long
Private Const SW_RESTORE As Long = 9&
Public Sub RestoreWindow()
Call ShowWindow(Me.hWnd, SW_RESTORE)
End Sub
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:
Private Sub Main()
Dim UserInput As String
UserInput = _
InputBox( _
"Please type in some text or press the cancel button.", _
"Test" _
)
If StrPtr(UserInput) = 0 Then
Call MsgBox("The cancel button was pressed!")
Else
Call MsgBox("You entered """ & UserInput & """!")
End If
End Sub
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:
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
If UnloadMode = vbFormControlMenu Then
Const Question As String = "Fenster wirklich schließen?"
If MsgBox(Question, vbQuestion Or vbYesNo) = vbNo Then
Cancel = Not Cancel
End If
End If
End Sub
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:
Private Declare Function FindWindow _
Lib "user32.dll" _
Alias "FindWindowA" _
( _
ByVal lpClassName As String, _
ByVal lpWindowName As String _
) As Long
Private Declare Function PostMessage _
Lib "user32.dll" _
Alias "PostMessageA" _
( _
ByVal hWnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long _
) As Long
Private Const WM_CLOSE As Long = &H10&
Private Sub Main()
Dim hWnd As Long
hWnd = FindWindow(vbNullString, "Rechner")
If hWnd <> 0 Then
If PostMessage(hWnd, WM_CLOSE, 0&, 0&) = 0& Then
Call MsgBox("Fehler!")
Else
Call MsgBox("Der Rechner sollte nun geschlossen sein!")
End If
Else
Call MsgBox("Der Rechner ist nicht geöffnet!")
End If
End Sub
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ß:
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
If Shift = vbAltMask Then
If KeyCode = vbKeyF4 Then
KeyCode = 0
End If
End If
End Sub
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:
Private Declare Function SetClassLong _
Lib "user32.dll" _
Alias "SetClassLongA" _
( _
ByVal hWnd As Long, _
ByVal nIndex As Long, _
ByVal dwNewLong As Long _
) As Long
Private Declare Function GetClassLong _
Lib "user32.dll" _
Alias "GetClassLongA" _
( _
ByVal hWnd As Long, _
ByVal nIndex As Long _
) As Long
Private Const GCL_STYLE As Long = -26&
Private Const CS_DROPSHADOW As Long = &H20000
Private Sub Form_Load()
Call SetClassLong( _
Me.hWnd, _
GCL_STYLE, _
GetClassLong(Me.hWnd, GCL_STYLE) Or CS_DROPSHADOW _
)
End Sub
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:Private Declare Function SetForegroundWindow Lib "user32.dll" ( _ ByVal hWnd As Long _ ) As Long
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:
Call SetForegroundWindow(FDummy.hWnd) Call FDummy.PopupMenu(Me.mnuPopup, , , , mnuPopupNotifyIcon)
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:
Private m_OldX As Long
Private m_OldY As Long
Private m_IsMoving As Boolean
Private Sub Form_Load()
m_IsMoving = False
End Sub
Private Sub Form_MouseDown( _
Button As Integer, _
Shift As Integer, _
X As Single, _
Y As Single _
)
m_OldX = X
m_OldY = Y
m_IsMoving = True
End Sub
Private Sub Form_MouseMove( _
Button As Integer, _
Shift As Integer, _
X As Single, _
Y As Single _
)
If m_IsMoving Then
Me.Top = Me.Top - m_OldY + Y
Me.Left = Me.Left - m_OldX + X
End If
End Sub
Private Sub Form_MouseUp( _
Button As Integer, _
Shift As Integer, _
X As Single, _
Y As Single _
)
m_IsMoving = False
End Sub
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
:
Call Me.Move((Screen.Width - Width) * 0.5, (Screen.Height - Height) * 0.5)
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:
' Deaktivieren des Elternformular des "modalen" Dialogs.
FOptions.Enabled = False
' Anzeigen des Dialogs.
Call FControl.Show
Weiters muß im Unload
-Ereignis von FControl
der nachfolgende Code hinzugefügt werden, um das Optionsformular wieder zu aktivieren:
FOptions.Enabled = True
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:
Private Sub Form_Unload(Cancel As Integer)
Dim Form As Form
For Each Form In Forms
Call Unload(Form)
Next Form
End Sub
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:
Private Declare Function LockWindowUpdate Lib "user32.dll" ( _
ByVal hWnd As Long _
) As Long
Private Sub LockWindow(ByVal hWnd As Long)
Call LockWindowUpdate(hWnd)
End Sub
Private Sub UnlockWindow()
Call LockWindowUpdate(0&)
End Sub
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:
Call LockWindow(Me.hWnd)
' Aktualisierungscode.
Call UnlockWindow
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:
Private Declare Function SendMessage _
Lib "user32.dll" _
Alias "SendMessageA" _
( _
ByVal hWnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
ByRef lParam As Long _
) As Long
Private Const WM_SETREDRAW As Long = &HB&
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:
' Aktualisieren unterbinden.
Call SendMessage(Control.hWnd, WM_SETREDRAW, 0&, 0&)
' Steuerelement hier manipulieren.
' Aktualisieren wieder zulassen.
Call SendMessage(Control.hWnd, WM_SETREDRAW, 1&, 0&)
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:
Private Declare Function GetSystemMenu Lib "user32.dll" ( _
ByVal hWnd As Long, _
ByVal bRevert As Long _
) As Long
Private Declare Function DeleteMenu Lib "user32.dll" ( _
ByVal hMenu As Long, _
ByVal nPosition As Long, _
ByVal wFlags As Long _
) As Long
Private Const MF_BYPOSITION As Long = &H400&
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:
Dim hMenu As Long, n As Long
hMenu = GetSystemMenu(Me.hWnd, False)
n = DeleteMenu(hMenu, 4&, MF_BYPOSITION)
If n = 0& Then
Call MsgBox("Menüeintrag kann nicht gelöscht werden.")
End If
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:
Private Declare Function GetSystemMenu Lib "user32.dll" ( _
ByVal hWnd As Long, _
ByVal bRevert As Long _
) As Long
Private Declare Function GetMenuItemCount Lib "user32.dll" ( _
ByVal hMenu As Long _
) As Long
Private Declare Function DrawMenuBar Lib "user32.dll" ( _
ByVal hWnd As Long _
) As Long
Private Declare Function RemoveMenu Lib "user32.dll" ( _
ByVal hMenu As Long, _
ByVal nPosition As Long, _
ByVal wFlags As Long _
) As Long
Private Const MF_BYPOSITION As Long = &H400&
Private Const MF_REMOVE As Long = &H1000&
Private Sub Form_Load()
Dim hMenu As Long, n As Long
hMenu = GetSystemMenu(Me.hWnd, 0&)
If hMenu <> 0& Then
n = GetMenuItemCount(hMenu)
If n > 0& Then
Call RemoveMenu(hMenu, CLng(n - 1), MF_BYPOSITION Or MF_REMOVE)
Call RemoveMenu(hMenu, CLng(n - 2), MF_BYPOSITION Or MF_REMOVE)
Call DrawMenuBar(Me.hWnd)
End If
End If
End Sub
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):
Private Declare Function DeleteMenu Lib "user32.dll" ( _
ByVal hMenu As Long, _
ByVal nPosition As Long, _
ByVal wFlags As Long _
) As Long
Private Declare Function GetSystemMenu Lib "user32.dll" ( _
ByVal hWnd As Long, _
ByVal bRevert As Long _
) As Long
Private Declare Function GetWindowLong _
Lib "user32.dll" _
Alias "GetWindowLongA" _
( _
ByVal hWnd As Long, _
ByVal nIndex As Long _
) As Long
Private Declare Function SetWindowLong _
Lib "user32.dll" _
Alias "SetWindowLongA" _
( _
ByVal hWnd As Long, _
ByVal nIndex As Long, _
ByVal dwNewLong As Long _
) As Long
Private Const GWL_STYLE As Long = -16&
Private Const MF_BYCOMMAND As Long = &H0&
Private Const SC_MINIMIZE As Long = &HF020&
Private Const WS_MINIMIZEBOX As Long = &H20000
Private Sub Form_Load()
Call DeleteMenu( _
GetSystemMenu(Me.hWnd, 0&), _
SC_MINIMIZE, _
MF_BYCOMMAND _
)
Call SetWindowLong( _
Me.hWnd, _
GWL_STYLE, _
CLng(GetWindowLong(Me.hWnd, GWL_STYLE) Xor WS_MINIMIZEBOX) _
)
End Sub
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:
Private Declare Function SetWindowPos Lib "user32.dll" ( _
ByVal hWnd As Long, _
ByVal hWndInsertAfter As Long, _
ByVal x As Long, _
ByVal y As Long, _
ByVal cx As Long, _
ByVal cy As Long, _
ByVal wFlags As Long _
) As Long
Private Const HWND_TOPMOST As Long = -1&
Private Const HWND_NOTOPMOST As Long = -2&
Private Const SWP_NOSIZE As Long = &H1&
Private Const SWP_NOMOVE As Long = &H2&
Private Const SWP_SHOWWINDOW As Long = &H40&
Private Const BaseError As Long = 512&
Private Sub Form_Load()
Me.AutoRedraw = True
End Sub
Private Sub tmrSetOnTop_Timer()
Call SetTopWindow(Me.hWnd)
Me.Print "Set to top at " & Time$
End Sub
Public Sub SetTopWindow(ByVal hWnd As Long)
If _
SetWindowPos( _
hWnd, _
HWND_TOPMOST, _
0&, _
0&, _
0&, _
0&, _
SWP_NOSIZE Or SWP_NOMOVE Or SWP_SHOWWINDOW _
) = 0& _
Then
Call Err.Raise( _
vbObjectError + BaseError + 1, _
"SetTopWindow", _
"Error bringing window on top." _
)
Else
If _
SetWindowPos( _
hWnd, _
HWND_NOTOPMOST, _
0&, _
0&, _
0&, _
0&, _
SWP_NOSIZE Or SWP_NOMOVE Or SWP_SHOWWINDOW _
) = 0& _
Then
Call Err.Raise( _
vbObjectError + BaseError + 1, _
"SetTopWindow", _
"Error bringing window on top." _
)
End If
End If
End Sub