Fenster Einbetten
Also ich hab das schon oft gehabt und bin auch schon oft gefragt worden.
Ich hab ein Fenster, und dieses soll in der Größe veränderbar sein. Mit 2 Einschränkungen : 1. die Form darf nicht kleiner sein als eine bestimmte Größe, und 2. die Form darf auch nicht größer werden als eine bestimmte Größe.
Das naheliegendste ist dann natürlich im Resize-Ereigniss die aktuellen Width- und Heighteigenschften auszulesen und gegebenenfalls zu korrigieren.
Das Dumme daran ist, daß das mächtig Scheiße aussieht. (um mal kein Blatt vor den Mund zu nehmen...*gg*) Es flackert und tut und macht - bloß nicht das was es soll.
Die nächste überlegung ist, vor dem Resize-Ereigniss das gleiche zu tun. Und daß geht mit dem AdressOf-Operator. 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 steht. (Das sieht jetzt alles sehr kryptisch aus, aber im Grunde ist es ganz einfach...ehrlich*g*)
Deklaration:Private WinOldProcMinMax As Long
Private Const GWL_WNDPROC = (-4)
Private Const WM_GETMINMAXINFO = &H24
Private lX1 As Long, lX2 As Long, lY1 As Long, 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
ptMaxTrackSize As POINTAPI
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 CopyMemory1 Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Sub CopyMemory2 Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As Any, Source As Any, ByVal Length As Long)
Aktiviert wird das ganze mit dem AdressOf-Operator. Deswegen auch erst ab VB5.
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
Public Sub UnloadMinMax(Form As Form)
SetWindowLong Form.hWnd, GWL_WNDPROC, WinOldProcMinMax
End Sub
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
If uMsg = WM_GETMINMAXINFO Then
Dim MM As MINMAXINFO
CopyMemory1 MM, lParam, Len(MM)
MM.ptMinTrackSize.x = lX1
MM.ptMinTrackSize.y = lY1
MM.ptMaxTrackSize.x = lX2
MM.ptMaxTrackSize.y = lY2
CopyMemory2 lParam, MM, Len(MM)
ret = DefWindowProc(hWnd, uMsg, wParam, lParam)
Else
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-Ereigniss 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-Ereigniss der UnloadMinMax-Aufruf erfolgen.
Private Sub Form_Load()
SetMinMax Me, 200, 200, 500, 500
End Sub
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
UnloadMinMax Me
End Sub
So, daß ist das Grundprinzip der Funktion.
Im Modul 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-Ereigniss tritt beim beenden aus der IDE nämlich nicht ein.
Viel Spaß beim Probieren.