I have a Form with 2 Panels:
Panel1.BackColor is Color.Red
Panel2.BackColor is Color.Blue
When dragging panel1 to panel2, panel2 must take the color of panel1
When starting the drag operation panel1 must change color to white
When drag and drop is completed panel1 must return to color red.
All this is accomplished, but I still miss this:
if the drag and drop operation is cancelled (used dropping on other control, hitting ESC etc.) then the color of panel2 remains white, it does not revert to Color.Red.
How do I accomplish this?
I have tried to look at QueryContinueDrag, but can't seem to find a solution.
This is the code I have:
Public Class Form1
Private dragBoxFromMouseDown As Rectangle
Private Sub Panel1_MouseDown(sender As Object, e As MouseEventArgs) Handles Panel1.MouseDown
Dim dragSize As Size = SystemInformation.DragSize
dragBoxFromMouseDown = New Rectangle(New Point(e.X - (dragSize.Width / 2), e.Y - (dragSize.Height / 2)), dragSize)
End Sub
Private Sub Panel1_MouseMove(sender As Object, e As MouseEventArgs) Handles Panel1.MouseMove
If ((e.Button And MouseButtons.Left) = MouseButtons.Left) Then
If (Rectangle.op_Inequality(dragBoxFromMouseDown, Rectangle.Empty) And Not dragBoxFromMouseDown.Contains(e.X, e.Y)) Then
Panel1.BackColor = Color.White
Panel1.DoDragDrop(sender.name, DragDropEffects.All)
End If
End If
End Sub
Private Sub Panel2_DragEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles Panel2.DragEnter
If e.Data.GetData(DataFormats.Text).contains("Panel1") Then
e.Effect = DragDropEffects.Copy
End If
End Sub
Private Sub Panel2_DragDrop(sender As Object, e As DragEventArgs) Handles Panel2.DragDrop
Panel2.BackColor = Me.Controls(e.Data.GetData(DataFormats.Text)).backcolor
Me.Controls(e.Data.GetData(DataFormats.Text)).backcolor = Color.Red
End Sub
End Class
As you have mentioned, you should handle the QueryContinueDrag event of the source Panel, to determine what action is being performed. It could be Continue
, Drop
or Cancel
.
You want to restore the background color of the source Control when the current action is DragAction.Drop
or DragAction.Cancel
.
I've refactored some of the code presented here, because it contains some weird stuff.
For example, you can simply pass the Control instance to the DoDragDrop()
method, then verify with e.Data.GetDataPresent()
that it contains the Type you want to handle.
Also, some null checks are missing
Private panelQueryDragPosition As Point
Private Sub Panel1_MouseDown(sender As Object, e As MouseEventArgs) Handles Panel1.MouseDown
panelQueryDragPosition = e.Location
End Sub
Private Sub Panel1_MouseMove(sender As Object, e As MouseEventArgs) Handles Panel1.MouseMove
If e.Button = MouseButtons.Left AndAlso
(Math.Abs(e.X - panelQueryDragPosition.X) > SystemInformation.DragSize.Width OrElse
Math.Abs(e.Y - panelQueryDragPosition.Y) > SystemInformation.DragSize.Height) Then
Dim ctl = DirectCast(sender, Panel) ' The source Control cannot be null here
ctl.BackColor = Color.White
ctl.DoDragDrop(ctl, DragDropEffects.Copy)
End If
End Sub
Private Sub Panel1_QueryContinueDrag(sender As Object, e As QueryContinueDragEventArgs) Handles Panel1.QueryContinueDrag
If e.Action = DragAction.Drop OrElse e.Action = DragAction.Cancel Then
Dim ctl = DirectCast(sender, Control)
If ctl IsNot Nothing Then ctl.BackColor = Color.Red
End If
End Sub
Private Sub Panel2_DragEnter(sender As Object, e As DragEventArgs) Handles Panel2.DragEnter
If e.Data IsNot Nothing AndAlso e.Data.GetDataPresent(GetType(Panel)) Then
e.Effect = DragDropEffects.Copy
Else
e.Effect = DragDropEffects.None
End If
End Sub
Private Sub Panel2_DragDrop(sender As Object, e As DragEventArgs) Handles Panel2.DragDrop
Dim panel = DirectCast(sender, Panel)
If panel IsNot Nothing AndAlso e.Data IsNot Nothing AndAlso e.Data.GetDataPresent(GetType(Panel)) Then
Dim sourceControl = DirectCast(e.Data.GetData(GetType(Panel)), Panel)
panel.BackColor = sourceControl.BackColor
End If
End Sub