What's New
Q & A
Tip Jar
C# Helper...
Follow VBHelper on Twitter
MSDN Visual Basic Community
TitleSize Forms to Fit the Screen
Keywordssizing, resizing, forms, fit screen
CategoriesTips and Tricks, Tutorials

Size Forms to Fit the Screen

This tutorial describes several ways a program can handle different screen resolutions.

Suppose you carefully craft a form sized to fit your screen. You position every control exactly to achieve the perfect visual effect. Then you distribute the program and your customers run it on a screen with 640 x 480 pixels. You designed it with 800 x 600 pixels so the form doesn't fit.

Modern computers can work at many different resolutions depending on how many colors they display. My computer can run at these resolutions:

640 x 480 720 x 480 720 x 576 800 x 600
1024 x 768 1152 x 854 1280 x 1024 1600 x 1200

So what can you do to ensure that a form will look good at all resolutions? Here are some approaches you can take:

Design for the Smallest Screen

Design your form for the smallest screen the users will have, probably 640 x 480 pixels. When the screen is larger, you can center it, taking the task bar into account like this:

Private Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type

Private Declare Function SystemParametersInfo Lib "user32" _
    Alias "SystemParametersInfoA" (ByVal uAction As Long, _
    ByVal uParam As Long, ByRef lpvParam As RECT, _
    ByVal fuWinIni As Long) As Long
Private Const SPI_GETWORKAREA = 48

' Center the form taking the task bar
' into account.
Private Sub CenterForm(ByVal frm As Form)
Dim wa_info As RECT
Dim wa_wid As Single
Dim wa_hgt As Single

    If SystemParametersInfo(SPI_GETWORKAREA, _
        0, wa_info, 0) <> 0 _
        ' We got the work area bounds.
        ' Center the form in the work area.
        wa_wid = ScaleX(wa_info.Right, vbPixels, vbTwips)
        wa_hgt = ScaleY(wa_info.Bottom, vbPixels, vbTwips)
        ' We did not get the work area bounds.
        ' Center the form on the whole screen.
        wa_wid = Screen.Width
        wa_hgt = Screen.Height
    End If

    ' Center the form.
    frm.Move (wa_wid - Width) / 2, _
             (wa_hgt - Height) / 2
End Sub

Private Sub Form_Load()
    CenterForm Me
End Sub

This technique is simple. You only need to design the form once. It requires no special changes or rearrangement of controls at run time.

The disadvantage of this technique is that it does not take full advantage of the screen if it has a greater resolution than 640 x 480. If the screen is 800 x 600, you could display a lot more data.

This method also leaves some of the screen uncovered. That generally does not change the program's usability, but it can be distracting. Fortunately it's easy to cover the entire screen. Simply maximize the form by setting the WindowState property to vbMaximized. Then center the form's controls in the form. This is easiest if you place the controls inside a PictureBox. Then you only need to center the PictureBox.

' At design time we set:
'     ControlBox = False
'     Caption = ""
'     WindowState = Maximized
'     BorderStyle = FixedSingle 
Private Sub Form_Resize()
    picCenter.BorderStyle = vbBSNone
    picCenter.Move _
        (ScaleWidth - picCenter.Width) / 2, _
        (ScaleHeight - picCenter.Height) / 2
End Sub

If you like, you can add a picture or pattern to the form so the background is not completely blank.

A Note on Color Resolution

When you design for different resolutions, remember that color resolution and pixel resolution are related. On my computer, I can display 24-bit color at up to 1280 x 1024 pixels. If I go to 1660 x 1200 pixels, however, the system only has enough graphic memory to display 8-bit color (256 colors).

If you expect users to set their screens to use very high spatial resolution, you should also expect them to be using low color resolution. If your application displays photographic images or uses lots of colors, some of the colors may be lost. Your program may become unusable at these higher spatial resolutions. In that case, you may want to simply tell the user not to use higher spatial resolutions and you won't have to worry about them.

Resize Controls Automatically

Probably the most popular solution to the form sizing dilemma is to resize the form's controls automatically so they fill the form.

When the program starts, the Form_Load event handler calls subroutine SaveSizes. This routine saves each control's size and position in an array of the ControlPositionType user-defined type (UDT). Notice how the code handles Line controls specially because they have X1, Y1, X2, and Y2 properties instead of the usual Left, Top, Width, and Height properties.

When the form is resized, the Form_Resize event handler calls subroutine ResizeControls. This routine loops through each of the controls scaling their size and position properties appropriately for the form's new size.

Private Type ControlPositionType
    Left As Single
    Top As Single
    Width As Single
    Height As Single
    FontSize As Single
End Type

Private m_ControlPositions() As ControlPositionType
Private m_FormWid As Single
Private m_FormHgt As Single

' Save the form's and controls' dimensions.
Private Sub SaveSizes()
Dim i As Integer
Dim ctl As Control

    ' Save the controls' positions and sizes.
    ReDim m_ControlPositions(1 To Controls.Count)
    i = 1
    For Each ctl In Controls
        With m_ControlPositions(i)
            If TypeOf ctl Is Line Then
                .Left = ctl.X1
                .Top = ctl.Y1
                .Width = ctl.X2 - ctl.X1
                .Height = ctl.Y2 - ctl.Y1
                .Left = ctl.Left
                .Top = ctl.Top
                .Width = ctl.Width
                .Height = ctl.Height
                On Error Resume Next
                .FontSize = ctl.Font.Size
                On Error GoTo 0
            End If
        End With
        i = i + 1
    Next ctl

    ' Save the form's size.
    m_FormWid = ScaleWidth
    m_FormHgt = ScaleHeight
End Sub

' Arrange the controls for the new size.
Private Sub ResizeControls()
Dim i As Integer
Dim ctl As Control
Dim x_scale As Single
Dim y_scale As Single

    ' Don't bother if we are minimized.
    If WindowState = vbMinimized Then Exit Sub

    ' Get the form's current scale factors.
    x_scale = ScaleWidth / m_FormWid
    y_scale = ScaleHeight / m_FormHgt

    ' Position the controls.
    i = 1
    For Each ctl In Controls
        With m_ControlPositions(i)
            If TypeOf ctl Is Line Then
                ctl.X1 = x_scale * .Left
                ctl.Y1 = y_scale * .Top
                ctl.X2 = ctl.X1 + x_scale * .Width
                ctl.Y2 = ctl.Y1 + y_scale * .Height
                ctl.Left = x_scale * .Left
                ctl.Top = y_scale * .Top
                ctl.Width = x_scale * .Width
                If Not (TypeOf ctl Is ComboBox) Then
                    ' Cannot change height of ComboBoxes.
                    ctl.Height = y_scale * .Height
                End If
                On Error Resume Next
                ctl.Font.Size = y_scale * .FontSize
                On Error GoTo 0
            End If
        End With
        i = i + 1
    Next ctl
End Sub
Note that this example does not scale controls within other controls. For example, if you place a TextBox inside a PictureBox, the TextBox's position and dimensions are relative to the PictureBox not the form. This example does not handle this case.

This example also does not stretch pictures.

For a more complete example, see the Stretchable control in my book Custom Controls Library.

This technique fills the form with controls but it doesn't give the user any new information it just makes things bigger. That's okay if you are only increasing the form size slightly, perhaps from a screen size of 640 x 480 to one of 720 x 480, but it looks a bit silly if you go from a 640 x 480 screen to 1600 x 1200 pixels. In the later case, the result looks sort of like it was drawn in crayon. The following technique provides the best result.

Resize Specific Controls

The best method for resizing a form is to make certain scrollable controls resize to fill the extra space. For example, a ListBox or Grid can grow to use the available area and give the user access to new information.

Unfortunately this kind of application is hardest to program because you need to decide yourself which controls can give the user more information by expanding.

In the Form_Resize event handler, resize specific controls that contain scrollable areas to take best advantage of the form's new size. For example, a ListBox, Grid, or TreeView control may be able to display more information when the form is enlarged.

Note that you do not need to arrange the controls if the form is minimized because the user cannot see the controls. Note also that the code should never try to give a control a width or height that is less than zero. I usually set minimum sizes at 120 twips.

' Make the controls fit.
Private Sub Form_Resize()
Const MARGIN As Single = 120

Dim wid As Single
Dim hgt As Single

    ' Don't bother if we're minimized.
    If WindowState = vbMinimized Then Exit Sub

    ' See how wide we can make the name and address fields.
    wid = ScaleWidth - MARGIN - txtName.Left
    If wid < 120 Then wid = 120
    txtName.Width = wid
    txtStreet.Width = wid
    txtCity.Width = wid

    ' See how big we can make the assignments list.
    wid = ScaleWidth - 2 * MARGIN
    If wid < 120 Then wid = 120
    hgt = ScaleHeight - MARGIN - lstAssignments.Top
    If hgt < 120 Then hgt = 120
    lstAssignments.Move _
        lstAssignments.Left, lstAssignments.Top, _
        wid, hgt
End Sub

For information on controls that automatically resize to fit the form, controls (such as scrolled and paned windows aka splitters) that can help with limited screen space, and for controls that can help in arranging specific controls, see my book Custom Controls Library.

The following Download button includes all three of the previous Zip files.
Copyright © 1997-2010 Rocky Mountain Computer Consulting, Inc.   All rights reserved.