Maintaining Relative Sizing of Controls on a Form | | In VB6, it was an ordeal to keep controls sized in proportion to one another. The developer had to write several calculations in the Resize Event Handler of the form to keep everything in the right place with the right size. Using Panels, Docking, and Anchoring in .NET helps take the sting out of maintaining these sizes.
Recently, someone asked me to help them with a Windows Form in VB.NET. He wanted to keep two ListBox controls the same size as the form was resized. To do this, he had written dozens of lines of code in the Resize Event Handler of the form to calculate the height, width and position of each of the controls on the form. He was having some trouble getting it all straight in the end.
In VB6, this was the common approch to this problem. On a resize, you calculated all the appropriate dimensions and locations for your controls, then put everything in its place. This led to some incredibly unpredictable results when the calculations were not quite right. Most of us recall seeing controls seem to randomly size themselves and jump around when resizing a form. This task can be tackled much more easily in .NET.
.NET offers the Dock and Anchor properties to help take some of the hassle out of maintaining control sizes and positions. These properties, along with the Panel control, can take dozens of lines down to just a few. The solution discussed is available for download here.
Let's take a look at the necessary code:
Create a form, and add three panels - pnlLeft, pnlRight, then pnlMiddle. Dock these Left, Right, and Fill, respectively. Then add some controls, anchoring as follows:- ListBoxes - Top, Left, Bottom, Right
- Labels - Top, Left
- Buttons - None
The form should look like this in the designer:

Now, add a variable to the form:
| Private MiddleWidth As Integer = -1 |
In the constructor for the form, add the following line to set MiddleWidth:
| Me.MiddleWidth = Me.pnlMiddle.Width |
This variable will store the width of the middle panel (containing the buttons) for use in calculating the widths of the ListBoxes. Now, add a handler for the Resize Event of the form that looks like this:
Private Sub Form1_Resize(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles MyBase.Resize
If Me.MiddleWidth > -1 Then
'MiddleWidth Initialized - Set Panel Widths
Me.pnlLeft.Width = CInt((Me.Width - Me.MiddleWidth) / 2)
Me.pnlRight.Width = CInt((Me.Width - Me.MiddleWidth) / 2)
End If
End Sub |
Note that the code first checks to make sure MiddleWidth has been set. This is necessary because the Resize event will fire during InitializeComponent when the controls are being created and the form is sized. We do not want to resize controls until all of this has been done.
And that's it! Run the application and resize the form, and you will see that the ListBoxes maintain equal widths. With just a few simple lines of code, the controls maintain relative sizes. This example makes the controls resize to the same width, but it does not take much more effort to maintain relative sizes that are not exactly the same. Simply declare a ratio variable, set it in the constructor (much like the MiddleWidth variable), and calculate the widths using that ratio in the resize event.
Download the code from this article - DynamicResizeSample.zip (28KB) |