Introduction
I've seen several VB.NET articles posted here regarding proportionally resizing and repositioning controls on a VB.NET form when the form is resized. I tried some of them with varying levels of success, including Docking and Anchoring controls. None seemed to get me exactly what I needed. I need for controls to reposition and resize without being fixed to any border and without growing and overlaying each other.
Listed below is a solution I came up with implementing the behavior in a small Resizer
class that can be included and used in any form easily.
The complete code is listed below. I welcome any thought/ideas for improvements. Also, while this class is written in VB, rewriting in C# would be simple.
Thanks.
Background
The Resizer
class has two public
methods:
FindAllControls(control)
ResizeAllControls(control)
The class is used by first calling the FindAllControls
method during the Form's Load
event. Internally, the class stores the original relative position and size of each control on a form in an internal Dictionary
object.
Then, in the Form's Resize
event, ResizeAllControls
is called to adjust controls proportionally based on their stored original information and the new form size.
The FindAllControls
and ResizeAllControls
procedures are written to recursively process container controls. There are many examples available online to demonstrate this method of processing container controls.
Font sizes are also modified during resizing. A new font size is calculated using an average of the control's relative height and width change.
Note: Label controls will not resize if their AutoSize
property is set to 'True
'.
Again, any suggestions for improvement are welcome.
Using the Code
After adding the class file, Resizer.vb, to a VB.NET project, three lines of Form code are needed to use the ReSize
class:
- Declare a form-level instance of the
Resizer
class:
Dim rs as New Resizer
- In the
Form_Load
event procedure, call the FindAllControls
method, passing the form as a parameter:
rs.FindAllControls(Me)
- In the
Form_Resize
event procedure, call the ResizeAllControls
method, passing the form as a parameter:
rs.ResizeAllControls(Me)
A complete Form code example:
Public Class Form1
Dim rs As New Resizer
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
rs.FindAllControls(Me)
End Sub
Private Sub Form1_Resize(sender As Object, e As EventArgs) Handles Me.Resize
rs.ResizeAllControls(Me)
End Sub
End Class
The complete class code is as follows:
Public Class Resizer
Private Structure ControlInfo
Public name As String
Public parentName As String
Public leftOffsetPercent As Double
Public topOffsetPercent As Double
Public heightPercent As Double
Public originalHeight As Integer
Public originalWidth As Integer
Public widthPercent As Double
Public originalFontSize As Single
End Structure
Private ctrlDict As Dictionary(Of String, ControlInfo) = New Dictionary(Of String, ControlInfo)
Public Sub FindAllControls(thisCtrl As Control)
For Each ctl As Control In thisCtrl.Controls
Try
If Not IsNothing(ctl.Parent) Then
Dim parentHeight = ctl.Parent.Height
Dim parentWidth = ctl.Parent.Width
Dim c As New ControlInfo
c.name = ctl.Name
c.parentName = ctl.Parent.Name
c.topOffsetPercent = Convert.ToDouble(ctl.Top) / Convert.ToDouble(parentHeight)
c.leftOffsetPercent = Convert.ToDouble(ctl.Left) / Convert.ToDouble(parentWidth)
c.heightPercent = Convert.ToDouble(ctl.Height) / Convert.ToDouble(parentHeight)
c.widthPercent = Convert.ToDouble(ctl.Width) / Convert.ToDouble(parentWidth)
c.originalFontSize = ctl.Font.Size
c.originalHeight = ctl.Height
c.originalWidth = ctl.Width
ctrlDict.Add(c.name, c)
End If
Catch ex As Exception
Debug.Print(ex.Message)
End Try
If ctl.Controls.Count > 0 Then
FindAllControls(ctl)
End If
Next
End Sub
Public Sub ResizeAllControls(thisCtrl As Control)
Dim fontRatioW As Single
Dim fontRatioH As Single
Dim fontRatio As Single
Dim f As Font
For Each ctl As Control In thisCtrl.Controls
Try
If Not IsNothing(ctl.Parent) Then
Dim parentHeight = ctl.Parent.Height
Dim parentWidth = ctl.Parent.Width
Dim c As New ControlInfo
Dim ret As Boolean = False
Try
ret = ctrlDict.TryGetValue(ctl.Name, c)
If (ret) Then
ctl.Width = Int(parentWidth * c.widthPercent)
ctl.Height = Int(parentHeight * c.heightPercent)
ctl.Top = Int(parentHeight * c.topOffsetPercent)
ctl.Left = Int(parentWidth * c.leftOffsetPercent)
f = ctl.Font
fontRatioW = ctl.Width / c.originalWidth
fontRatioH = ctl.Height / c.originalHeight
fontRatio = (fontRatioW +
fontRatioH) / 2 ctl.Font = New Font(f.FontFamily,
c.originalFontSize * fontRatio, f.Style)
End If
Catch
End Try
End If
Catch ex As Exception
End Try
If ctl.Controls.Count > 0 Then
ResizeAllControls(ctl)
End If
Next End Sub
End Class
Points of Interest
VB.NET - Simple class that dynamically Resizes and Repositions all controls when a Form is resized, including Font sizes with only three lines of code in your form.
History
- 3rd September, 2015: Initial version