Die Community zu .NET und Classic VB.
Menü

VB 5/6-Tipp 0231: Größenveränderung eines Formulars begrenzen

 von 

Beschreibung 

Wer sein Fenster beim Resize auf ein Minimum oder Maximum beschränken will, kann sich dieses Tips bedienen.

Schwierigkeitsgrad:

Schwierigkeitsgrad 1

Verwendete API-Aufrufe:

CallWindowProcA (CallWindowProc), RtlMoveMemory (CopyMemory1), RtlMoveMemory (CopyMemory2), DefWindowProcA (DefWindowProc), SetWindowLongA (SetWindowLong)

Download:

Download des Beispielprojektes [2,97 KB]

'Dieser Quellcode stammt von http://www.activevb.de
'und kann frei verwendet werden. Für eventuelle Schäden
'wird nicht gehaftet.

'Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum.
'Ansonsten viel Spaß und Erfolg mit diesem Source!

'------------- Anfang Projektdatei Project1.vbp -------------
'--------- Anfang Formular "Form1" alias Form1.frm  ---------

Option Explicit

Private Sub Form_Load()
    Dim R As SIZEPAR
    
    R.xMin = 150
    R.yMin = 100
    R.xMax = 300
    R.yMax = 200
    Call Init(Me, R)
End Sub

Private Sub Form_Unload(Cancel As Integer)
    Call UnHook
End Sub
'---------- Ende Formular "Form1" alias Form1.frm  ----------
'--------- Anfang Modul "Module1" alias Module1.bas ---------

Option Explicit

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)

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

Public Type SIZEPAR
    xMin As Long
    yMin As Long
    xMax As Long
    yMax As Long
End Type

Private Const GWL_WNDPROC As Long = -4&
Private Const WM_GETMINMAXINFO As Long = &H24&

Private WinOldProc As Long
Private spR As SIZEPAR
Private Frm As Form

Public Sub Init(F As Form, R As SIZEPAR)
    spR = R
    Set Frm = F
    WinOldProc = SetWindowLong(Frm.hWnd, GWL_WNDPROC, _
                               AddressOf WindowProc)
End Sub

Public Sub UnHook()
    Call SetWindowLong(Frm.hWnd, GWL_WNDPROC, WinOldProc)
End Sub

Private Function WindowProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal _
                            wParam As Long, ByVal lParam&) As Long
    Dim Result As Long
    Dim MM As MINMAXINFO
    
    If uMsg = WM_GETMINMAXINFO And Frm.WindowState = 0 Then
        Call CopyMemory1(MM, lParam, Len(MM))
        
        MM.ptMaxPosition.x = 0
        MM.ptMaxPosition.y = 0
        MM.ptMaxSize.x = Screen.Width / Screen.TwipsPerPixelX
        MM.ptMaxSize.y = Screen.Height / Screen.TwipsPerPixelY
        
        MM.ptMinTrackSize.x = spR.xMin
        MM.ptMinTrackSize.y = spR.yMin
        MM.ptMaxTrackSize.x = spR.xMax
        MM.ptMaxTrackSize.y = spR.yMax
        
        Call CopyMemory2(lParam&, MM, Len(MM))
        Result = DefWindowProc(hWnd, uMsg, wParam, lParam)
    Else
        Result = CallWindowProc(WinOldProc, hWnd, uMsg, _
                                  wParam, lParam)
    End If
    
    WindowProc = Result
End Function
'---------- Ende Modul "Module1" alias Module1.bas ----------
'-------------- Ende Projektdatei Project1.vbp --------------

Tipp-Kompatibilität:

Windows/VB-VersionWin32sWin95Win98WinMEWinNT4Win2000WinXP
VB4
VB5
VB6

Hat dieser Tipp auf Ihrem Betriebsystem und mit Ihrer VB-Version funktioniert?

Ja, funktioniert!

Nein, funktioniert nicht bei mir!

VB-Version:

Windows-Version:

Ihre Meinung  

Falls Sie Fragen zu diesem Artikel haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.

Archivierte Nutzerkommentare 

Klicken Sie diesen Text an, wenn Sie die 20 archivierten Kommentare ansehen möchten.
Diese stammen noch von der Zeit, als es noch keine direkte Forenunterstützung für Fragen und Kommentare zu einzelnen Artikeln gab.
Aus Gründen der Vollständigkeit können Sie sich die ausgeblendeten Kommentare zu diesem Artikel aber gerne weiterhin ansehen.

Kommentar von Dieter Feld am 14.06.2006 um 14:36

Hallo,

mir ist aufgefasllen, dass viele Code nicht
ausreichen erklärt werden.

Es wäre toll ( für Anfänger, aber auch erfahrenen Progs )
an den entsprechenden Stellen im Code ein 1-2 Zeiler als
Kommentar der Handlung / Aufgabe.

Toll finde ich die fertigen Zips zum herunterladen und
direkt mit VB6 zu testen.

Mfg
User

Kommentar von Timo Böhme am 17.05.2006 um 19:13

Nachtrag: In der kompilierten EXE stürzte das Programm (Trotz Unhook) immer wieder ab. Musste es wieder entfernen. Auch während das Programm lief, stürzte es ab. Ohne den Hook, sehe ich wieder grün für mein Programm.

Timo

Kommentar von Timo Böhme am 17.05.2006 um 12:06

Super Tipp. Danke. Erfüllt genau den Zweck.

Kommentar von Informatix am 13.11.2005 um 02:58

Wenn ich diese Methode benutze und Access 97-Anwendung über X-Button beende, wird die Anwendung zwar beendet aber gewisse Dinge werden nicht durchgeführt. Dazu gehört u.a. Speichern der Letzten Position von Access und die .ldb-Datei wird auch nicht gelöscht. Es wird nur das Fenster zerstört aber Access eigene Routinen werden nicht durchgeführt, die normalerweise beim Beenden ablaufen. Hat Jemand eine Idee wie man diese Routine entsprechend anpassen kann.

Kommentar von Achim am 06.07.2005 um 13:00

Hallo ....,


Ich bin noch sehr unerfahren in VB.

Wie bekomme ich diese Beispiele ans Laufen?

Kommentar von Erik am 11.04.2005 um 11:40

In dem direkt hier unten von Amegon gezeigtem Beispiel gibt es nur Probleme, wenn man eine Mindestgröße festlegen will. Denn wenn man mit der Maus den Rahmen unter ein gewisses Niveau zieht, also verkleinert, kommt es zu einem Laufzeitfehler, sofern andere Elemente sich an der Größe des Formulares orientieren. Es wird nämlich erst der Rahmen verkleinert, und dann erst wird die Größe geprüft.

Kommentar von Amegon am 07.05.2004 um 11:45

gibt auch ne kürzere methode,
flackert vielleciht n bisschen, macht aber nix :)
in der formBla_Rezize...

If Me.Width > 500 Then Me.Width = 500
If Me.Height > 300 Then Me.Width = 300

Kommentar von Michael Eger am 07.12.2003 um 15:55

Ich habe auch das Problem mit dem Max Button, die form verschwindet einfach. Weiter unten habe ich gelesen, daß in der Funktion 'WindowProc' etwas geändert werden muß. Vielleicht könnte mal jemand posten, was geändert werden muß.

Gruß Michael

Kommentar von Markus am 02.06.2003 um 16:43

Hab es zwar benutzt um die Window
Move Message abzufangen , aber es klappt
wunderbar so :-)

Kommentar von Horst Stapper am 18.06.2001 um 02:25

Ich habe diesen Tip schon vor ein paar Monaten ausprobiert.
Leider funktioniert das ganze überhaupt nicht, schon garnicht mit MDI-Childs.

Kommentar von Goetz Reinecke am 15.06.2001 um 09:37

Hallo Viper, klar das geht bestimmt auch über Resize. Sieht nur ein bißchen unschön aus, wenn sich das Fenster einen kurzen Augenblick vergrößert und dann wieder zusammenzieht.

Kommentar von Viper am 12.06.2001 um 15:20

Wieso muss man hier Subclassing verwenden ? Man kann das Problem doch auch nur mit der Resize Funktion lösen !
MFG viper

Kommentar von alex am 11.05.2001 um 14:59

Sorry Götz, hat sich erledigt funktioniert perfekt. Du hast mir nicht alle Änderungen geschickt !! trotzdem vielen Dank !! mfg Alex

Kommentar von alex am 11.05.2001 um 09:02

Hallo Götz
Danke für deine Hilfe. Hab jetzt die Funktion WindowProc nach deiner Vorgabe ausgetauscht doch jetzt stürtzt mein Programm sammt VB schon beim testen total ab. Kannst du mir sagen an was das jetzt nun wieder liegen könnte ! mfg Alex

Kommentar von Alex am 09.05.2001 um 09:16

Hab auch Problem beim Maximieren, zwar verschwindet das Formular nicht aber nur noch ein teil ist sichtbar auf dem Bildschirm !! Weiss jemand Rat ????

Kommentar von Michael Weber am 08.05.2001 um 18:18

Wenn man diesen Tip verwendet ist offensichtlich kein maximieren der Form mehr möglich.
Sobald man maximieren will, verschwindet die Form im Hintergrund und reagiert nicht mehr.
Btw: bei mir gab es keine böse Überraschung beim beenden via Stopp-Button aus der IDE heraus.

Kommentar von Götz Reinecke am 07.10.2000 um 20:22

Na, Logo!
Wenn in der IDE der Stop-Button betätigt wird, wird beim Beenden des Programms kein Uload-Ereignis ausgelöst.
Dadurch wird das initierte Sublcassing nicht ordnungsgemäß beendet.
Daher das Programm nur über den x-Button oder programmäßig über Unload. Ganz so wie es nacher in der exe geschehen soll (wo es dann ja auch keinen Stop-Button gibt).Grüße
Götz

Kommentar von fill am 07.10.2000 um 20:06

AUFGEPASS: wenn ihr diesen Tipp verwendet und das Programm mit dem "Stopp" Button beendet erlebt ihr eine BÖSE Überraschung!

Kommentar von Gill Davids am 04.10.2000 um 17:08

Hallo! Ich habe gerade an anderer Stelle Ihres Internetangebots die Lösung gefunden. Es tut mir leid, ich hab noch nicht so viel Erfahrung mit VB. MfG Gill Davids
PS: Es wäre sehr nett, wenn Sie diese Notiz auf der Website mit diesem Beitrag löschen könnten.

Kommentar von Gill Davids am 04.10.2000 um 17:00

Hallo!
Ich beziehe mich auf http://www.activevb.de/cgi-bin/VBquest.pl?/vb/VBtips/VBtip0231.shtml - Resize eines Formulars begrenzen
Wenn ich möchte, daß das Fenster überhaupt nicht in der Größe geändert werden kann, sondern nur minimiert oder wieder hergestellt werden können soll, muß ich dann nur die Resize-Begrenzungs-Werte auf 0 setzen? Oder funktioniert das anders?
Vielen Dank, Ihr Gill Davids