拖放后将PictureBox捕捉到按钮 [英] Snap PictureBox to Buttons after Drag and Drop

查看:102
本文介绍了拖放后将PictureBox捕捉到按钮的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在制作《战舰》游戏,并且使用按钮作为网格(玩家面板)。我正在使用图片框作为运送工具,并且正在尝试制作图片框,以使图片框可以捕捉到与其碰撞的按钮。

I'm making a Battleship game, and I'm using buttons as the grid(playerboard). I'm using a picture box as the ship, and I'm trying to make it so that the picturebox snaps to the buttons that it is colliding with.

我已经完成了拖放和碰撞部分,但是我在为按钮捕捉部分上苦苦挣扎。图片框是两个按钮的大小。我试图通过使用picturebox.left = button.left将picturebox与按钮对齐,但是它选择了两者中的错误按钮。

I have already done the drag and drop, and collision part, but I'm struggling with the snapping to buttons part. The picture box is the size of two buttons. I tried to align the picturebox with the buttons, by using picturebox.left = button.left, but it chooses the wrong button of the two.

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 并调用 GetChildAtPoin t() ,在的位置获取子控件,并指定 GetChildAtPointSkip.Disabled 作为第二个参数,这样搜索将不包括禁用的 PictureBox ,而是所有

To get the button which you want to snap to you can temporarily disable the PictureBox and call GetChildAtPoint() on the form to get the child control at the location of the PictureBox, specifying GetChildAtPointSkip.Disabled as the second parameter so that the search won't include your disabled PictureBox but all the other controls above/below it.

之后,您可以将 PictureBox 的坐标设置为按钮。

After that you can just set the PictureBox's coordinates to that of the button.

您的代码也可以进行一些改进:

There are also a few improvements that can be made to your code:


  • 您可以使用 MouseUp 事件 ,而不是 MouseLeave 放下后立即更新图片框的位置。

  • You can use the MouseUp event instead of MouseLeave to update the picture box's position immediately after you drop it.

设置捕捉时图片框的X坐标和Y坐标(不仅是其中的一个, Left = X,Top = Y ),以便将其正确捕捉到在按钮的左上角。

Set both the X- and Y-coordinates for the picture box when snapping (not just one of them, Left = X, Top = Y) so that it is snapped correctly in the top-left corner of the button.

在循环中,通过 Me.Controls.OfType(Of Button)(),而不只是 Me.Controls ,因为 OfType(Of TResult) 仅会得到 某种类型的控件(在本例中为 Button s)。例如,仅通过 Me.Controls 进行迭代将包含 PictureBox 本身,这可能会在将来引起问题(也许为何每次将其 BackColor 设置为 Control 的原因?)。

In the loop iterate through Me.Controls.OfType(Of Button)() instead of just Me.Controls, since OfType(Of TResult) will get only the controls of a certain type (in this case Buttons). Iterating through only Me.Controls will for example include the PictureBox itself which could cause issues in the future (perhaps that was the reason you set its BackColor to Control every time?).

话虽如此,该代码应该可以工作:

All that said, this code should work:

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

要记住的另一件事是使用 Andso 而不是 And OrElse 代替<$ c $中的 Or c>如果 AndAlso OrElse 之后的语句是 短路

Another thing to keep in mind is to use AndAlso instead of And, and OrElse instead of Or in If-statements since AndAlso and OrElse are short-circuited.

这篇关于拖放后将PictureBox捕捉到按钮的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆