Applying a minimum size to resizable forms

(Visual Basic 6)

Many times it is necessary to set a minimum size to which sizeable forms can be set. This is often the case with forms containing a number of controls, with the size of the controls being modified in the Resize event. If the form gets too small, the VB code would start setting negative Width and Height value, which obviously would cause an error.

There are three systems I have seen used to solve this problem. The best solution is to intercept the WM_GETMINMAXINFO message that is sent to a window each time it is resized. This message isn't directly available in Visual Basic 6, however, and so the window will need to be subclassed. For information on how to do this, see the Microsoft Knowledge Base article Q185733. This feature has been added as a direct property for VB.net forms, so this is obviously the ideal solution for VB.net programmers.

Personally I dislike direct subclassing in VB, as it creates problems if the subclassing isn't "undone" correctly (for example, clicking the "Stop" button in the VB IDE whilst a subclass is in place can cause the application to crash) so I tend to avoid this method.

Another method I have seen is to check the Width and Height at the beginning of the Resize event. If either are too small, they are set back to the minimum acceptable values and the Exit Sub statement is used to prevent further processing. The fact that the properties were changed then causes the Resize event to fire again immediately, with the new size in place.

This works but is very ugly; when the window is sized below its minimum size with the "Show window contents while dragging" option set on in Windows (Control Panel > Display / Effects) it flickers like mad and looks terrible.

I have decided on a third method to resolve this problem in my own applications. The approach is slightly different: instead of preventing the user sizing the window too small, we'll just stop resizing the controls once the window gets smaller than our acceptable point.

First some example code demonstrating the problem...

Create a new Standard EXE project and add a textbox to the default form. Set the properties of the textbox as follows:

Left240
MultiLineTrue
ScrollBars3 - Both
Top240

Add the following code to the form:

Private Sub Form_Resize() 'Set the size of the textbox to match the size of the form With Text1 .Move .Left, .Top, Me.Width - .Left * 2, Me.Height - .Top * 3 End With End Sub

Run the project and try resizing the form. You'll see that the textbox always changes its size to match that of the form -- just how we want. But resize the form to its minimum size and you'll get a VB runtime error; not so nice.

So here's the "ugly" approach to solving this problem. We'll set a minimum size of the form as 3000 by 3000 twips. Replace the existing Resize event code with the following:

Private Sub Form_Resize() Const MINWIDTH As Long = 3000 Const MINHEIGHT As Long = 3000 If Me.Width < MINWIDTH Then Me.Width = MINWIDTH Exit Sub End If If Me.Height < MINHEIGHT Then Me.Height = MINHEIGHT Exit Sub End If 'Set the size of the textbox to match the size of the form With Text1 .Move .Left, .Top, Me.Width - .Left * 2, Me.Height - .Top * 3 End With End Sub

Now run the project and resize the window so that it's very small. This time there will be no runtime error and the size will essentially be limited to a reasonable minimum. However, all the time the window is being sized below that minimum point, the window flickers rapidly and various lines appear across the window is it is resized.

So here is the approach I usually use in situations like this. It doesn't impose a minimum size at all (the user can set the window to be tiny if they want to) but it does limit the way the resizing of the controls in the window is handled. If the window is sized too small, the controls are simply lost off the right and bottom edges of the window.

Replace the existing Resize event code with the following:

Private Sub Form_Resize() Dim lUseWidth As Long Dim lUseHeight As Long Const MINWIDTH As Long = 3000 Const MINHEIGHT As Long = 3000 'Copy the current width and height to our variables lUseWidth = Me.Width lUseHeight = Me.Height 'Set a minimum limit on the lUseWidth and lUseHeight variables If lUseWidth < MINWIDTH Then lUseWidth = MINWIDTH If lUseHeight < MINHEIGHT Then lUseHeight = MINHEIGHT 'Set the size of the textbox using the values in lUseWidth and lUseHeight With Text1 .Move .Left, .Top, lUseWidth - .Left * 2, lUseHeight - .Top * 3 End With End Sub

Once again, run the project and resize the window so that it becomes smaller than the minimum size we have set. This time you'll notice that the window will size down to virtually nothing, but still no runtime errors occur. If you watch the scrollbars on the textbox as you size, you'll see that the textbox just stops resizing when the window gets below a certain width and height.

When you're faced with this "minimum size" problem, you may always find that one solution works better than another. Hopefully this article gives you an additional approach to think about when solving this problem.

If you have any comments or suggestions regarding this article, please don't hesitate to contact me.

This article is copyright © Adam Dawes, 2000.