Rubrik: Oberfläche · Fenster | VB-Versionen: VB5, VB6 | 09.05.01 |
Fenstergröße einschränken Mit dieser Routine kann man die Größenänderung eines Fenster auf ein Minium/Maximum einschränken. | ||
Autor: Wolfgang Kluge | Bewertung: | Views: 23.799 |
www.vbwelt.de | System: Win9x, WinNT, Win2k, WinXP, Win7, Win8, Win10, Win11 | Beispielprojekt auf CD |
Manchmal ist es notwendig oder erwünscht, daß zwar ein Fenster in der Größe vberändert werden darf, jedoch mit zwei Einschränkungen:
1. das Fenster darf nicht kleiner sein als eine bestimmte Größe,
2. das Fenster darf auch nicht größer werden als eine bestimmte Größe.
Das naheliegendste ist dann natürlich im Resize-Ereignis die aktuellen Width- und Height-Eigenschaften auszulesen und gegebenenfalls zu korrigieren. Das "Dumme" daran ist, daß das wirklich nicht gerade schön aussieht. Es flackert und tut und macht - bloß nicht das, was es soll.
Die nächste Überlegung ist, vor dem Resize-Ereignis das gleiche zu tun. Und das geht mit dem AdressOf-Operator - jedoch erst ab VB5. Die API-Funktion SetWindowLong bietet an, einen Pointer auf eine Funktion zu setzten, die dann alle Windows-Funktionen aufnimmt.
Man lege sich also ein Modul in einem Projekt an, in dem folgendes stehtDas sieht jetzt alles sehr kryptisch aus, aber im Grunde ist es ganz einfach...ehrlich)
Option Explicit Private WinOldProcMinMax Private Const GWL_WNDPROC = (-4) ' Die Nachricht WM_GETMINMAXINFO wird an ein Fenster ' geschickt, bevor es vergrößert bzw. verkleinert wird Private Const WM_GETMINMAXINFO = &H24 Private lX1 As Long Private lX2 As Long Private lY1 As Long Private lY2 As Long Private Type POINTAPI x As Long y As Long End Type Private Type MINMAXINFO ptReserved As POINTAPI ptMaxSize As POINTAPI ptMaxPosition As POINTAPI ptMinTrackSize As POINTAPI ' Minimale Größe ptMaxTrackSize As POINTAPI ' Maximale Größe End Type Private Declare Function DefWindowProc Lib "user32" _ Alias "DefWindowProcA" ( _ ByVal hWnd As Long, _ ByVal wMsg As Long, _ ByVal wParam As Long, _ ByVal lParam As Long) As Long Private Declare Function CallWindowProc Lib "user32" _ Alias "CallWindowProcA" ( _ ByVal lpPrevWndFunc As Long, _ ByVal hWnd As Long, _ ByVal Msg As Long, _ ByVal wParam As Long, _ ByVal lParam As Long) As Long Private Declare Function SetWindowLong Lib "user32" _ Alias "SetWindowLongA" ( _ ByVal hWnd As Long, _ ByVal nIndex As Long, _ ByVal dwNewLong As Long) As Long Private Declare Sub CopyMemory Lib "kernel32" _ Alias "RtlMoveMemory" ( _ ByVal Destination As Any, _ ByVal Source As Any, _ ByVal Length As Long) Private Declare Sub CopyMemory1 Lib "kernel32" _ Alias "RtlMoveMemory" ( _ Destination As MINMAXINFO, _ ByVal Source As Long, _ ByVal Length As Long) Private Declare Sub CopyMemory2 Lib "kernel32" _ Alias "RtlMoveMemory" ( _ ByVal Destination As Long, _ Source As MINMAXINFO, _ ByVal Length As Long)
Aktiviert wird das ganze mit dem AdressOf-Operator.
Deswegen auch erst ab VB5.
Alle nachfolgenden Prozeduren müssen noch im Modul "abgelegt" werden.
' AufrufProzedur ' Am besten im Form_Load-Ereignis aufrufen Public Sub SetMinMax(Form As Form, x1 As Long, _ y1 As Long, x2 As Long, y2 As Long) WinOldProcMinMax = SetWindowLong(Form.hWnd, _ GWL_WNDPROC, AddressOf WindowProcMinMax) lX1 = x1 lX2 = x2 lY1 = y1 lY2 = y2 End Sub ' Normalzustand wiederherstellen ' WICHTIG! Vor dem Beenden der Form aufrufen Public Sub UnloadMinMax(Form As Form) SetWindowLong Form.hWnd, GWL_WNDPROC, _ WinOldProcMinMax End Sub ' Hier kommen alle Nachrichten an, die an daß Fenster ' geschickt werden Private Function WindowProcMinMax(ByVal hWnd As Long, _ ByVal uMsg As Long, ByVal wParam As Long, _ ByVal lParam As Long) As Long Dim ret As Long Dim MM As MINMAXINFO If uMsg = WM_GETMINMAXINFO Then CopyMemory1 MM, lParam, Len(MM) With MM .ptMinTrackSize.x = lX1 .ptMinTrackSize.y = lY1 .ptMaxTrackSize.x = lX2 .ptMaxTrackSize.y = lY2 End With CopyMemory2 lParam, MM, Len(MM) ret = DefWindowProc(hWnd, uMsg, wParam, lParam) Else ' Wenn andere Nachricht, dann "durchlassen" ret = CallWindowProc(WinOldProcMinMax, hWnd, uMsg, _ wParam, lParam) End If WindowProcMinMax = ret End Function
Ab hier braucht es nur noch den Aufruf aus (irgend-)einer Form, der am besten im Form_Load-Ereignis steht. Natürlich kann der Maximalwert auch weit über dem Windows-Standard liegen...
Damit Windows keinen Grund zum Beschweren hat, sollte spätestens im Form_QueryUnload-Ereignis der UnloadMinMax-Aufruf erfolgen.
' Größeneinschränkung festlegen Private Sub Form_Load() SetMinMax Me, 200, 200, 500, 500 End Sub ' WICHTIG: Normalzustand wiederherstellen Private Sub Form_QueryUnload(Cancel As Integer, _ UnloadMode As Integer) UnloadMinMax Me End Sub
So, das ist das Grundprinzip der Funktion.
Im Modul (Download-File) gehts noch einen paar Schritte weiter.
Dort werden mehrere Formen auf einmal unterstützt (in einem Array gespeichert) und man kann auch nur eine Größe angeben (die anderen bleiben dann auf dem Windows-Standard). Auch ist es möglich, die Werte während der Laufzeit zu verändern. Desweiteren kann man wahlweiße den Minimieren-, den Maximieren-, den Wiederherstellen- und/oder den Schließen-Button deaktivieren. Im Normalfall nicht wichtig, da dies auch in den Eigenschaften der Form geschehen kann, doch hier gehts auch in MDI-Childformen.
Das einzigste, das man jetzt noch beachten muß, ist daß man seine Programme beim Debuggen nicht in der IDE beendet (Stop), ohne vorher den Aufruf UnloadMinMax gesetzt zu haben. Ein Unload-Ereignis tritt beim Beenden aus der IDE nämlich nicht ein.
Viel Spaß beim Probieren.