对齐网格 MDI 子窗体 vb.net

snap to grid MDI child forms vb.net

我正在 Visual Basic 中开发一个模块化仪表板,它从一个空容器开始,我无法添加模块来填充它。

父窗体是一个 MDI 容器,每个模块都是一个具有固定大小的子 MDI 窗体。

我想在用户创建新子窗体时以及将其中一个子窗体移动到容器内时(就像它们被磁化到该网格一样)将所有子窗体对齐到一个网格。

我该怎么做?谢谢

如果我很清楚你需要这样的东西:

    Private Class ImaginaryGrid

    ' You can change Columns and Rows as you want
    Shared Rows As Integer = 3
    Shared Cols As Integer = 3

    Private Shared Function SnapToGrid(target As Form) As Point

        Dim AllW As Integer = Screen.PrimaryScreen.WorkingArea.Width
        Dim AllH As Integer = Screen.PrimaryScreen.WorkingArea.Height

        Dim parent = target.MdiParent
        If parent IsNot Nothing Then
            AllW = target.MdiParent.ClientSize.Width
            AllH = target.MdiParent.ClientSize.Height
        End If

        Dim currentPoint As Point = target.Location

        Dim stepW As Integer = CInt(AllW / Cols)
        Dim stepH As Integer = CInt(AllH / Rows)

        Dim targetCol As Integer = CInt(currentPoint.X \ stepW)
        Dim targetRow As Integer = CInt(currentPoint.Y \ stepH)

        Dim newX As Integer = targetCol * stepW
        Dim newY As Integer = targetRow * stepH

        target.Location = New Point(newX, newY)
        target.Width = stepW
        target.Height = stepH

    End Function

    Shared Sub AttachFormToStayInGrid(frm As Form)
        AddHandler frm.ResizeEnd, Sub()
                                      SnapToGrid(frm)
                                  End Sub
        SnapToGrid(frm)
    End Sub

End Class

用法:

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    ImaginaryGrid.AttachFormToStayInGrid(Me)
End Sub

按照下面的评论进行更改(如果需要):

这是基于与 G3nt_M3caj 的建议相同的想法的增强版本:

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