選択したコントロールに最も近いコントロールを取得する簡単な方法はありますか?
ピクチャーボックスと他のいくつかの移動コントロールがあります。画像ボックスに最も近いコントロールを削除したい。
したがって、すべてのコントロールの位置を取得し、画像ボックスの場所に最も近い場所でそれを削除する必要があります。それを最善の方法で行う方法がわかりません。
選択したコントロールに最も近いコントロールを取得する簡単な方法はありますか?
ピクチャーボックスと他のいくつかの移動コントロールがあります。画像ボックスに最も近いコントロールを削除したい。
したがって、すべてのコントロールの位置を取得し、画像ボックスの場所に最も近い場所でそれを削除する必要があります。それを最善の方法で行う方法がわかりません。
あなたの場合の「最も近い」が実際に「私の写真ボックスの場所に最も近い場所」を意味する場合、最も簡単なのは次のとおりです。
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
これは、提供されたコントロールがベース コントロールに対して 8 つの領域のうちの 1 つにあるかどうかをチェックすることによって、"最も近い" を計算するサンプル フォーム全体です。コードの半分は、説明したシナリオを模倣しようとしてセットアップされています。下と下が作品の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