拖放后将 PictureBox 捕捉到按钮
Snap PictureBox to Buttons after Drag and Drop
我正在制作一款战舰游戏,我正在使用按钮作为网格(玩家面板)。我正在使用一个图片框作为船,我正在努力使图片框捕捉到它与之碰撞的按钮。
我已经完成了拖放和碰撞部分,但我正在努力处理捕捉到按钮的部分。图片框是两个按钮的大小。我试图通过使用 picturebox.left = button.left 将图片框与按钮对齐,但它选择了两个错误的按钮。
Dim Off As Point
Private Sub picDestroyer_MouseDown(sender As Object, e As MouseEventArgs) Handles picDestroyer.MouseDown
Off.X = MousePosition.X - sender.Left 'Click and Drag ship
Off.Y = MousePosition.Y - sender.Top
End Sub
Private Sub picDestroyer_MouseMove(sender As Object, e As MouseEventArgs) Handles picDestroyer.MouseMove
If e.Button = MouseButtons.Left Then
sender.Left = MousePosition.X - Off.X 'Click and Drag ship
sender.Top = MousePosition.Y - Off.Y
End If
End Sub
Private Sub picDestroyer_DoubleClick(sender As Object, e As EventArgs) Handles picDestroyer.DoubleClick
If picDestroyer.Size = New Size(52, 21) Then 'Rotate Pic if double clicked
picDestroyer.Size = New Size(21, 52)
ElseIf picDestroyer.Size = New Size(21, 52) Then
picDestroyer.Size = New Size(52, 21)
End If
End Sub
Private Sub picDestroyer_MouseLeave(sender As Object, e As EventArgs) Handles picDestroyer.MouseLeave
For Each button In Me.Controls
If picDestroyer.Bounds.IntersectsWith(button.bounds) Then
button.backcolor = Color.Red
picDestroyer.BackColor = SystemColors.Control
End If
If picDestroyer.Bounds.IntersectsWith(button.bounds) And picDestroyer.Size = New Size(52, 21) Then
picDestroyer.Top = button.top
End If
If picDestroyer.Bounds.IntersectsWith(button.bounds) And picDestroyer.Size = New Size(21, 52) Then
picDestroyer.Left = button.left
End If
Next
要获取您想要对齐的按钮,您可以暂时禁用 PictureBox
并调用 GetChildAtPoint()
on the form to get the child control at the location of the PictureBox
, specifying GetChildAtPointSkip.Disabled
作为第二个参数,这样搜索就不会包括您禁用的 PictureBox
但所有其他控件 above/below 它。
之后,您只需将 PictureBox
的坐标设置为按钮的坐标即可。
还可以对您的代码进行一些改进:
您可以使用 MouseUp
event 而不是 MouseLeave
来在您放下图片框后立即更新它的位置。
在对齐时为图片框设置X-和Y-coordinates(不只是其中一个,Left = X, Top = Y
),以便在top-left 按钮的角。
在循环中遍历 Me.Controls.OfType(Of Button)()
而不仅仅是 Me.Controls
,因为 OfType(Of TResult)
将获得 只有 控件某种类型(在本例中为 Button
s)。例如,仅迭代 Me.Controls
将包括 PictureBox
本身,这可能会在将来引起问题(也许这就是您每次将其 BackColor
设置为 Control
的原因?) .
综上所述,这段代码应该可以工作:
If e.Button = Windows.Forms.MouseButtons.Left Then
picDestroyer.Enabled = False 'Temporarily disable the picture box so that it isn't included in the child search.
Dim ChildBelowDestroyer As Control = Me.GetChildAtPoint(picDestroyer.Location, GetChildAtPointSkip.Disabled) 'Look for any child control that isn't disabled.
picDestroyer.Enabled = True 'Re-enable the picture box.
If ChildBelowDestroyer Is Nothing OrElse _
ChildBelowDestroyer.GetType() IsNot GetType(Button) Then
Return 'Do not continue if no child was found below the picture box, or if the child is not a button.
End If
picDestroyer.Location = ChildBelowDestroyer.Location 'Snap the picture box to the button (sets the X- and Y-coordinates).
For Each button In Me.Controls.OfType(Of Button)() 'OfType() to only look for buttons.
If picDestroyer.Bounds.IntersectsWith(button.Bounds) Then
button.BackColor = Color.Red
picDestroyer.BackColor = SystemColors.Control
End If
Next
End If
要记住的另一件事是使用 AndAlso
instead of And
, and OrElse
instead of Or
in If
-statements since AndAlso
and OrElse
are short-circuited.
我正在制作一款战舰游戏,我正在使用按钮作为网格(玩家面板)。我正在使用一个图片框作为船,我正在努力使图片框捕捉到它与之碰撞的按钮。
我已经完成了拖放和碰撞部分,但我正在努力处理捕捉到按钮的部分。图片框是两个按钮的大小。我试图通过使用 picturebox.left = button.left 将图片框与按钮对齐,但它选择了两个错误的按钮。
Dim Off As Point
Private Sub picDestroyer_MouseDown(sender As Object, e As MouseEventArgs) Handles picDestroyer.MouseDown
Off.X = MousePosition.X - sender.Left 'Click and Drag ship
Off.Y = MousePosition.Y - sender.Top
End Sub
Private Sub picDestroyer_MouseMove(sender As Object, e As MouseEventArgs) Handles picDestroyer.MouseMove
If e.Button = MouseButtons.Left Then
sender.Left = MousePosition.X - Off.X 'Click and Drag ship
sender.Top = MousePosition.Y - Off.Y
End If
End Sub
Private Sub picDestroyer_DoubleClick(sender As Object, e As EventArgs) Handles picDestroyer.DoubleClick
If picDestroyer.Size = New Size(52, 21) Then 'Rotate Pic if double clicked
picDestroyer.Size = New Size(21, 52)
ElseIf picDestroyer.Size = New Size(21, 52) Then
picDestroyer.Size = New Size(52, 21)
End If
End Sub
Private Sub picDestroyer_MouseLeave(sender As Object, e As EventArgs) Handles picDestroyer.MouseLeave
For Each button In Me.Controls
If picDestroyer.Bounds.IntersectsWith(button.bounds) Then
button.backcolor = Color.Red
picDestroyer.BackColor = SystemColors.Control
End If
If picDestroyer.Bounds.IntersectsWith(button.bounds) And picDestroyer.Size = New Size(52, 21) Then
picDestroyer.Top = button.top
End If
If picDestroyer.Bounds.IntersectsWith(button.bounds) And picDestroyer.Size = New Size(21, 52) Then
picDestroyer.Left = button.left
End If
Next
要获取您想要对齐的按钮,您可以暂时禁用 PictureBox
并调用 GetChildAtPoint()
on the form to get the child control at the location of the PictureBox
, specifying GetChildAtPointSkip.Disabled
作为第二个参数,这样搜索就不会包括您禁用的 PictureBox
但所有其他控件 above/below 它。
之后,您只需将 PictureBox
的坐标设置为按钮的坐标即可。
还可以对您的代码进行一些改进:
您可以使用
MouseUp
event 而不是MouseLeave
来在您放下图片框后立即更新它的位置。在对齐时为图片框设置X-和Y-coordinates(不只是其中一个,
Left = X, Top = Y
),以便在top-left 按钮的角。在循环中遍历
Me.Controls.OfType(Of Button)()
而不仅仅是Me.Controls
,因为OfType(Of TResult)
将获得 只有 控件某种类型(在本例中为Button
s)。例如,仅迭代Me.Controls
将包括PictureBox
本身,这可能会在将来引起问题(也许这就是您每次将其BackColor
设置为Control
的原因?) .
综上所述,这段代码应该可以工作:
If e.Button = Windows.Forms.MouseButtons.Left Then
picDestroyer.Enabled = False 'Temporarily disable the picture box so that it isn't included in the child search.
Dim ChildBelowDestroyer As Control = Me.GetChildAtPoint(picDestroyer.Location, GetChildAtPointSkip.Disabled) 'Look for any child control that isn't disabled.
picDestroyer.Enabled = True 'Re-enable the picture box.
If ChildBelowDestroyer Is Nothing OrElse _
ChildBelowDestroyer.GetType() IsNot GetType(Button) Then
Return 'Do not continue if no child was found below the picture box, or if the child is not a button.
End If
picDestroyer.Location = ChildBelowDestroyer.Location 'Snap the picture box to the button (sets the X- and Y-coordinates).
For Each button In Me.Controls.OfType(Of Button)() 'OfType() to only look for buttons.
If picDestroyer.Bounds.IntersectsWith(button.Bounds) Then
button.BackColor = Color.Red
picDestroyer.BackColor = SystemColors.Control
End If
Next
End If
要记住的另一件事是使用 AndAlso
instead of And
, and OrElse
instead of Or
in If
-statements since AndAlso
and OrElse
are short-circuited.