Resizing objects on a forms maximize

Hi all,

I have a windows form which acts as a menu system. It has three sets of 7 buttons. These 7 buttons are positioned vertically down a form in 3 rows. What I would like is that if the user hits the maximise icon and maximises the form, I want all of the buttons to grow in proportion to the size change. I've looked at anchoring and docking but my form always comes out as a mess! Any ideas guys?

I'm using vs 2004.
LVL 3
FMabeyAsked:
Who is Participating?
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
Assuming your form is laid out this way:

B1   B2   B3   B4   B5   B6   B7
B8   B9   B10 B11 B12 B13 B14
B15 B16 B17 B18 B19 B20 B21

...and the buttons should take up the whole form:

Public Class Form1

    Private Sub Form1_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
        If Me.WindowState <> FormWindowState.Minimized Then
            PositionButtons()
        End If
    End Sub

    Private Sub PositionButtons()
        Dim margin As Integer = 12
        Dim padding As Integer = 6
        Dim btnWidth As Integer = (Me.ClientRectangle.Width - (margin * 2) - (padding * 6)) / 7
        Dim btnHeight As Integer = (Me.ClientRectangle.Height - (margin * 2) - (padding * 2)) / 3
        Dim ctl As Control
        Dim row, col As Integer
        For i As Integer = 1 To 21
            row = (i - 1) \ 7
            col = (i - 1) Mod 7
            ctl = GetControlByName("Button" & i, Me)
            If (Not (ctl Is Nothing)) AndAlso (TypeOf ctl Is Button) Then
                Dim btn As Button = DirectCast(ctl, Button)
                btn.Size = New Size(btnWidth, btnHeight)
                btn.Location = New Point(margin + (col * btnWidth) + (col * padding), margin + (row * btnHeight) + (row * padding))
            End If
        Next
    End Sub

    Private Function GetControlByName(ByVal ctlName As String, ByVal container As Control) As Control
        ctlName = ctlName.ToLower
        For Each c As Control In container.Controls
            If c.Name.ToLower = ctlName Then
                Return c
            ElseIf c.HasChildren Then
                Dim ctl As Control = GetControlByName(ctlName, c)
                If Not (ctl Is Nothing) Then
                    Return ctl
                End If
            End If
        Next
        Return Nothing
    End Function

End Class
0
 
kvimalCommented:
Set the button size proportion to the size of the Form height and width.
0
 
icrCommented:
If you are using .NET 2.0 use a TableLayoutPanel
0
Cloud Class® Course: Python 3 Fundamentals

This course will teach participants about installing and configuring Python, syntax, importing, statements, types, strings, booleans, files, lists, tuples, comprehensions, functions, and classes.

 
FMabeyAuthor Commented:
Unfortunately I'm not using .NET 2.0.
Kvimal, can you explain a little further? Maybe with an example?
0
 
icrCommented:
An alternative to "finding" the controls is to create the controls in code and storing them in an array. This means you don't have random buttons in the designer where changes in layout don't actually mean anything, and changes can be applied in bulk to the buttons. However, individual changes may be more difficult if you aren't familiar with adding events etc. and you have no visual designer to help you.

Public Class Form1
    Const xButtonCount As Integer = 7
    Const yButtonCount As Integer = 3
    Const buttonMargin As Integer = 12
    Const buttonPadding As Integer = 6

    Dim Buttons(Width, Height) As Button

    Public Sub New()
        Dim x, y As Integer
        Me.SuspendLayout()
        For x = 0 To xButtonCount - 1
            For y = 0 To yButtonCount - 1
                ' NOTE: The resize event will get called after this, so we can leave the
                '       sizing and position to the resize event.
                Buttons(x, y) = New Button()
                Me.Controls.Add(Buttons(x, y))
            Next
        Next
        Me.ResumeLayout()
        Me.InitializeComponent()
    End Sub

    Private Sub Form1_ClientSizeChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.ClientSizeChanged
        If Me.WindowState = FormWindowState.Minimized Then
            Return
        End If

        Dim x, y As Integer
        Dim buttonSize As Size = New Size((Me.ClientRectangle.Width - (buttonMargin * 2) - (buttonPadding * (xButtonCount - 1))) / xButtonCount, (Me.ClientRectangle.Height - (buttonMargin * 2) - (buttonPadding * (yButtonCount - 1))) / yButtonCount)
        Me.SuspendLayout()
        For x = 0 To xButtonCount - 1
            For y = 0 To yButtonCount - 1
                Buttons(x, y).Size = buttonSize
                Buttons(x, y).Location = New Point(buttonMargin + (x * buttonSize.Width) + (x * buttonPadding), buttonMargin + (y * buttonSize.Height) + (y * buttonPadding))
            Next
        Next
        Me.ResumeLayout()
    End Sub
End Class

Even if you do choose to go Idle_Mind's route (which has it's own benefits) I would suggest you only do the lookup at the beginning and then use the array references after that. It will make the code slightly more performant (and as resize is called often it can help):

Public Class Form1
    Const colButtonCount As Integer = 7
    Const rowButtonCount As Integer = 3
    Const buttonMargin As Integer = 12
    Const buttonPadding As Integer = 6

    Dim Buttons(Width, Height) As Button

    Public Sub New()
        InitializeComponent()
        Dim ctl As Control
        For row As Integer = 0 To rowButtonCount - 1
            For col As Integer = 0 To colButtonCount - 1
                ctl = GetControlByName("button" & ((row * colButtonCount) + col + 1), Me)
                If (Not (ctl Is Nothing)) AndAlso (TypeOf ctl Is Button) Then
                    Buttons(col, row) = ctl
                End If
            Next
        Next
        ' Becuse we have already called InitializeComponent to add the controls so we can find them
        ' the ClientSizeChanged event has already been called. Because of this we need to manualy recall it
        ' ourselves to start with the correct layout.
        Form1_ClientSizeChanged(Me, EventArgs.Empty)
    End Sub

    Private Sub Form1_ClientSizeChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.ClientSizeChanged
        If Me.WindowState = FormWindowState.Minimized Then
            Return
        End If

        Dim x, y As Integer
        Dim buttonSize As Size = New Size((Me.ClientRectangle.Width - (buttonMargin * 2) - (buttonPadding * (colButtonCount - 1))) / colButtonCount, (Me.ClientRectangle.Height - (buttonMargin * 2) - (buttonPadding * (rowButtonCount - 1))) / rowButtonCount)
        Me.SuspendLayout()
        For x = 0 To colButtonCount - 1
            For y = 0 To rowButtonCount - 1
                If Not Buttons(x, y) Is Nothing Then
                    Buttons(x, y).Size = buttonSize
                    Buttons(x, y).Location = New Point(buttonMargin + (x * buttonSize.Width) + (x * buttonPadding), buttonMargin + (y * buttonSize.Height) + (y * buttonPadding))
                End If
            Next
        Next
        Me.ResumeLayout()
    End Sub

    Private Function GetControlByName(ByVal ctlName As String, ByVal container As Control) As Control
        ctlName = ctlName.ToLower
        For Each c As Control In container.Controls
            If c.Name.ToLower = ctlName Then
                Return c
            ElseIf c.HasChildren Then
                Dim ctl As Control = GetControlByName(ctlName, c)
                If Not (ctl Is Nothing) Then
                    Return ctl
                End If
            End If
        Next
        Return Nothing
    End Function
End Class
0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
Soooooo many ways to do it...

Nice comments icr.  I just wanted to post a clear, straight forward algorithm that could be easily followed.  As you have pointed out, though, it can certainly be improved.   ;)

0
 
icrCommented:
I would agree your solution is the easiest to follow. However, as the resize event gets called frequently as the form is being resized the more optimal you can make it the less "tearing" will occur. You could certainly optimise it a lot more, but then it would be harder to understand and thus maintain.
0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
Another idea would be to trap the WM_EXITSIZEMOVE msg and only adjust the buttons when the user lets go AFTER they finish resizing the form.
http://msdn2.microsoft.com/en-us/library/ms632623.aspx
0
 
FMabeyAuthor Commented:
Thanks guys... I will have a look at the solutions offered and then allocated hte points accordingly.

Cheers.
0
 
FMabeyAuthor Commented:
Just to keep this alive and to let you know I've not abandoned it... Some other things have come up which I am dealing with so I will be trying out the ideas provided as soon as I can! Thanks for our help.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.