Pspl
Pspl

Reputation: 1474

Enable other event while dragging an object

I'm developing a console where I want to drag a button to a grid:

interface example

To drag the button, I use the following procedure:

Public drag As Boolean = False
Public ptX As Integer = 0
Public ptY As Integer = 0
Public btn As Button

Private Sub MoveButton_MouseDown(sender As Object, e As MouseEventArgs) Handles MoveButton.MouseDown
    drag = True
    btn = CType(sender, Button)
    ptX = e.X : ptY = e.Y
End Sub

Private Sub MoveButton_MouseMove(sender As Object, e As MouseEventArgs) Handles MoveButton.MouseMove
    If drag Then
        btn.Location = New Point(btn.Location.X + e.X - ptX, btn.Location.Y + e.Y - ptY)
        Me.Refresh()
    End If
End Sub

Private Sub MoveButton_MouseUp(sender As Object, e As MouseEventArgs) Handles MoveButton.MouseUp
    drag = False
End Sub

So far, so good! This works fine for that matter. However, I'm trying to highlight the cell while hoovering the button on it like this:

interface example

To do so, I tried to do the following:

Private Sub CellA1_MouseHover(sender As Object, e As EventArgs) Handles CellA1.MouseHover
    If drag Then
        CellA1.BackColor = Color.Red
    End If
End Sub

Of course I can't do that, unless I, somehow, enable the CellA1.MouseHover event while dragging the MoveButton.

Can anyone help me with this?

If, however, you're having a struggling will to help me further, my last goal is to place the MoveButton on the red cell place:

interface example

But feel free to don't help me at all with this part of the procedure since I have no code to perform this yet. Any help will be very appreciated. And, as always, thank you all in advance.

Upvotes: 1

Views: 274

Answers (1)

Visual Vincent
Visual Vincent

Reputation: 18310

Since your mouse is not actually on the PictureBox when you drag the button it will never raise any mouse events. What you can do instead is to call the GetChildAtPoint() method of your form to get the control behind the button. Once you have that just verify that the name starts with "Cell" and change the back color.

To snap to the cell's location you'll need to indicate to MouseUp which cell we're currently at. Simply store the cell control in a variable and you can then just set yourButton.Location = currentCell.Location

Here are the changes I've made to your code, commented for clarity:

Public drag As Boolean = False
Public ptX As Integer = 0
Public ptY As Integer = 0
Public btn As Button
Public prevCtrl As Control = Nothing 'Store the previous Cell the button was dragged over.
'                                     We need this to be able to reset the BackColor of the Cell, 
'                                     and also so that you can snap to its location once you drop the button.

Private Sub MoveButton_MouseDown(sender As Object, e As MouseEventArgs) Handles MoveButton.MouseDown
    'No changes made here.
    drag = True
    btn = CType(sender, Button)
    ptX = e.X : ptY = e.Y
End Sub

Private Sub MoveButton_MouseMove(sender As Object, e As MouseEventArgs) Handles MoveButton.MouseMove
    If drag Then
        btn.Location = New Point(btn.Location.X + e.X - ptX, btn.Location.Y + e.Y - ptY)

        'Go 1 pixel up, or else GetChildAtPoint() will return the button instead of the control behind it.
        Dim LookPoint As Point = Point.Subtract(btn.Location, New Size(0, 1))

        'Get the control located below/behind the button.
        Dim ControlBelow As Control = Me.GetChildAtPoint(LookPoint, GetChildAtPointSkip.Invisible Or GetChildAtPointSkip.Disabled) 'Ignore invisible or disabled controls.

        'Check so that the previous cell is not also the current cell. If they're the same then we won't change anything.
        If prevCtrl IsNot ControlBelow Then

            'Ok, the current cell and the previous cell are not the same.
            'Now check if there was any previous cell at all.
            If prevCtrl IsNot Nothing Then
                'There was a previous cell, but since the button 
                'is no longer hovering over it we reset its BackColor.
                prevCtrl.BackColor = Color.White
                prevCtrl = Nothing
            End If

            'Check that there infact is a control behind the button,
            'and also check that its name starts with "Cell".
            If ControlBelow IsNot Nothing AndAlso ControlBelow.Name.StartsWith("Cell", StringComparison.OrdinalIgnoreCase) Then
                'The control behind the button is a valid Cell. Change its BackColor.
                ControlBelow.BackColor = Color.Red
                prevCtrl = ControlBelow 'The previous cell is now the current cell.
            End If

        End If

        'Me.Refresh() - this is a very unnecessary call, it will just eat CPU. The form does not need to be redrawn at this point.
    End If
End Sub

Private Sub MoveButton_MouseUp(sender As Object, e As MouseEventArgs) Handles MoveButton.MouseUp
    'Check if we dragged the button. At this point prevCtrl is the current cell (if it's not Nothing).
    If drag = True AndAlso prevCtrl IsNot Nothing Then
        btn.Location = prevCtrl.Location 'Snap to the cell's location.
        prevCtrl.BackColor = Color.White 'Reset the cell's BackColor.
        prevCtrl = Nothing 'Reset this since we're no longer dragging the button.
    End If

    drag = False
End Sub

And it works like a charm!

Drag & Drop example

Snap example

Upvotes: 2

Related Questions