【问题标题】:Snap PictureBox to Buttons after Drag and Drop拖放后将 PictureBox 捕捉到按钮
【发布时间】:2017-01-23 03:27:20
【问题描述】:

我正在制作一款战舰游戏,我使用按钮作为网格(播放器)。我正在使用图片框作为船,并且我正在尝试使图片框捕捉到它正在碰撞的按钮。

我已经完成了拖放和碰撞部分,但我正在努力处理按钮部分。图片框是两个按钮的大小。我尝试使用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

【问题讨论】:

    标签: vb.net drag-and-drop alignment snapping


    【解决方案1】:

    要获取您想要捕捉的按钮,您可以暂时禁用PictureBox 并在表单上调用GetChildAtPoint() 以获取位于PictureBox 位置的子控件,将GetChildAtPointSkip.Disabled 指定为第二个参数,这样搜索就不会包括您禁用的PictureBox,而是它上方/下方的所有其他控件。

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

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

    • 您可以使用MouseUp event 代替MouseLeave 来更新图片框的位置。

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

    • 在循环中遍历Me.Controls.OfType(Of Button)() 而不仅仅是Me.Controls,因为OfType(Of TResult)获得某种类型的控件(在本例中为Buttons) .例如,仅迭代 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 代替And,并在If 中使用OrElse 代替Or,因为AndAlsoOrElseshort-circuited

    【讨论】:

    • 在 if 语句中添加 Exit For 后,按钮背景色不再变为红色。 picDestroyer.top = button.top 和 picDestroyer.Left = button.left 也不再有效。我还结合了 if 语句,我的代码看起来与您提供的相同。感谢您的帮助
    • @Erika :嗯,这很奇怪......那我得试试代码了。
    • @Erika:我已经用新代码和一些解释更新了整个答案。希望它会是你所需要的!
    • 非常感谢您的帮助!当我尝试If e.Button = Windows.Forms.MouseButtons.Left Then 时,e.button 下划线表示“e.button 不是“system.eventargs”的成员。我完全摆脱了 if 语句,它似乎仍然有效。谢谢你的帮助,非常感谢!
    • @Erika:很高兴我能帮上忙! -- 要让e.Button 工作,您必须有一个适当的事件声明。获得一个的最佳方法是删除任何现有的处理程序,然后从 Visual Studio 的事件框中选择事件。 MouseUp 的正确声明是:Private Sub picDestroyer_MouseUp(sender As Object, e As MouseEventArgs) Handles picDestroyer.MouseUp - 注意 "e As MouseEventArgs"
    猜你喜欢
    • 2011-08-16
    • 2012-04-02
    • 1970-01-01
    • 2015-02-24
    • 2020-12-20
    • 1970-01-01
    • 2012-06-04
    • 1970-01-01
    • 2014-05-24
    相关资源
    最近更新 更多