Ближайший контроль VB.net

Есть ли простой способ получить элемент управления, ближайший к выбранному элементу управления?

У меня есть коробка с картинками и некоторые другие движущиеся элементы управления. Я хочу удалить ближайший к окну изображения элемент управления.

Поэтому я должен получить положение всех элементов управления и удалить его с помощью местоположения, ближайшего к местоположению моего окна с изображением. Я не уверен, как это сделать наилучшим образом.


person René Stalder    schedule 14.05.2010    source источник


Ответы (2)


Если «ближайший» в вашем случае действительно означает «с местоположением, ближайшим к местоположению моего поля с изображением», то самым простым будет:

Me.Controls.Remove((From c In Me.Controls.Cast(Of Control)() Order By c.Location.Distance(PictureBox1.Location) Select c).Skip(1).Take(1)(0))

, где Distance определяется в таком модуле:

<System.Runtime.CompilerServices.Extension()> _
Public Function Distance(ByVal p1 As Point, ByVal p2 As Point) As Integer
    Return (p1.X - p2.X) * (p1.X - p2.X) + (p1.Y - p2.Y) * (p1.Y - p2.Y)
End Function
person GSerg    schedule 14.05.2010

Вот полный пример формы, которая вычисляет «ближайший», проверяя, находится ли предоставленный элемент управления в 1 из 8 областей относительно базового элемента управления. Половина кода настроена, пытаясь имитировать описанный вами сценарий. MainButton_Click и ниже - суть работы.

Option Explicit On
Option Strict On

Public Class Form1
    Private MainPB As PictureBox
    Private OtherPB As List(Of PictureBox)
    Private WithEvents MainButton As Button
    Private Rnd As New Random()
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'Setup the form with sample data
        Me.FormBorderStyle = Windows.Forms.FormBorderStyle.None

        Me.MainButton = New Button()
        Me.MainButton.Text = "Update"
        Me.MainButton.Left = 1
        Me.MainButton.Top = 20
        Me.Controls.Add(Me.MainButton)


        Me.Width = 1000
        Me.Height = 1000
        MainPB = New PictureBox()
        MainPB.BackColor = Color.Red
        MainPB.Width = 100
        MainPB.Height = 100
        MainPB.Left = (Me.Width \ 2) - (MainPB.Width \ 2)
        MainPB.Top = (Me.Height \ 2) - (MainPB.Height \ 2)
        Me.Controls.Add(MainPB)

        Me.OtherPB = New List(Of PictureBox)
        For I = 0 To 50
            Me.OtherPB.Add(New PictureBox())
            With Me.OtherPB(I)
                .BackColor = Color.Transparent
                .BorderStyle = BorderStyle.FixedSingle
                .Width = 50
                .Height = 50
            End With
            SetRandomPbLocation(Me.OtherPB(I))
            Me.Controls.Add(Me.OtherPB(I))
        Next
    End Sub
    Private Sub SetRandomPbLocation(ByVal pb As PictureBox)
        'Just sets a random location for the picture boxes and ensures that it doesn't overlap with the center PB
        Do While True
            pb.Left = Rnd.Next(1, Me.Width - pb.Width)
            pb.Top = Rnd.Next(1, Me.Height - pb.Height)
            If (pb.Right < Me.MainPB.Left OrElse pb.Left > Me.MainPB.Right) AndAlso (pb.Top > Me.MainPB.Bottom OrElse pb.Bottom < Me.MainPB.Top) Then
                Exit Do
            End If
        Loop
    End Sub
    Private Sub MainButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles MainButton.Click
        'Randomizes the location of the picture boxes
        For Each PB In Me.OtherPB
            SetRandomPbLocation(PB)
        Next
        'Will hold the closest control after the loop
        Dim ClosestPB As Control = Nothing
        Dim ClosestD, TempD As Double
        For Each PB In Me.OtherPB
            'Reset the control's background color
            PB.BackColor = Color.Transparent
            'Calculate the distance
            TempD = GetDistanceBetweenToControls(PB, Me.MainPB)
            If ClosestPB Is Nothing Then 'If this is the first time through the loop then just use this control as the closest
                ClosestPB = PB
                ClosestD = TempD
            ElseIf TempD < ClosestD Then 'Otherwise if this control is closer than the current closest
                ClosestPB = PB
                ClosestD = TempD
            End If
        Next
        'Set the closest controls background color so that we can see it
        ClosestPB.BackColor = Color.Blue
    End Sub
    Private Shared Function GetDistanceBetweenToControls(ByVal controlToCheck As Control, ByVal baseControl As Control) As Double
        If controlToCheck.Bottom < baseControl.Top Then
            If controlToCheck.Right < baseControl.Left Then 'Above and to the left
                Return DistanceBetweenTwoPoints(New Point(controlToCheck.Right, controlToCheck.Bottom), baseControl.Location)
            ElseIf controlToCheck.Left > baseControl.Right Then 'above and to the right
                Return DistanceBetweenTwoPoints(New Point(controlToCheck.Left, controlToCheck.Bottom), New Point(baseControl.Right, baseControl.Top))
            Else 'Above
                Return baseControl.Top - baseControl.Bottom
            End If
        ElseIf controlToCheck.Top > baseControl.Bottom Then
            If controlToCheck.Right < baseControl.Left Then 'Below and to the left
                Return DistanceBetweenTwoPoints(New Point(controlToCheck.Right, controlToCheck.Top), New Point(baseControl.Left, baseControl.Bottom))
            ElseIf controlToCheck.Left > baseControl.Right Then 'Below and to the right
                Return DistanceBetweenTwoPoints(controlToCheck.Location, New Point(baseControl.Right, baseControl.Bottom))
            Else 'Below
                Return controlToCheck.Top - baseControl.Bottom
            End If
        Else
            If controlToCheck.Right < baseControl.Left Then 'Left
                Return baseControl.Left - controlToCheck.Right
            ElseIf controlToCheck.Left > baseControl.Right Then 'Right
                Return controlToCheck.Left - baseControl.Right
            End If
        End If
    End Function
    Private Shared Function DistanceBetweenTwoPoints(ByVal point1 As Point, ByVal point2 As Point) As Double
        'Standard distance formula
        Return Math.Sqrt((Math.Abs(point2.X - point1.X) ^ 2) + (Math.Abs(point2.Y - point1.Y) ^ 2))
    End Function
End Class
person Chris Haas    schedule 14.05.2010