Search code examples
vb.netmdichild

snap to grid MDI child forms vb.net


I'm developping a modular dashboard in Visual Basic that starts as an empty container than i can add modules to populate it.

The parent form is an MDI container and every module is a child MDI form that have fixed size.

I'd like to snap all of that child form to a grid both when the user creates a new one and when moves one of it inside the container (like they are magnetized to that grid).

How can i do that? Thanks


Solution

  • Here's a beefed up version based on the same idea as G3nt_M3caj's suggestion:

    enter image description here

    Public Class Form1
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            ImaginaryGrid.Client = Me.Controls.OfType(Of MdiClient).FirstOrDefault
        End Sub
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim frm As New Form
            ImaginaryGrid.AttachFormToStayInGrid(frm)
        End Sub
    
        Private Class ImaginaryGrid
    
            Public Shared WithEvents Client As MdiClient
    
            Public Shared FixedChildSize As New Size(250, 150)
    
            Private Shared Function SnapToGrid(target As Form) As Rectangle
                Dim colX As Integer = target.Location.X / FixedChildSize.Width
                Dim colY As Integer = target.Location.Y / FixedChildSize.Height
                Dim newX As Integer = colX * FixedChildSize.Width
                Dim newY As Integer = colY * FixedChildSize.Height
    
                Return New Rectangle(New Point(newX, newY), FixedChildSize)
            End Function
    
            Shared Sub AttachFormToStayInGrid(frm As Form)
                frm.Size = FixedChildSize
                frm.FormBorderStyle = FormBorderStyle.FixedSingle
                frm.MdiParent = Client.Parent
                frm.Show()
                SnapChild(frm)
    
                AddHandler frm.ResizeEnd, Sub()
                                              SnapChild(frm)
                                          End Sub
                AddHandler frm.LocationChanged, Sub()
                                                    If frm.WindowState = FormWindowState.Normal Then
                                                        snapRectangle = SnapToGrid(frm)
                                                        Client.Refresh()
                                                    End If
                                                End Sub
            End Sub
    
            Private Shared Sub SnapChild(ByVal frm As Form)
                If frm.WindowState = FormWindowState.Normal Then
                    Dim rc As Rectangle = SnapToGrid(frm)
                    frm.Bounds = rc
                    snapRectangle = Nothing
                    Client.Refresh()
                End If
            End Sub
    
            Private Shared snapRectangle? As Rectangle
    
            Private Shared Sub Client_Paint(sender As Object, e As PaintEventArgs) Handles Client.Paint
                If snapRectangle.HasValue Then
                    e.Graphics.DrawRectangle(Pens.Black, snapRectangle)
                End If
            End Sub
    
        End Class
    
    End Class