Visto che ormai stavo scrivendo un po di codice vb.net (sopratutto per rinfrescarmi la memoria) ho aggiunto una piccola "chicca" per eventuali altri forumisti alla quale può servire, ovvero il cambio del cursore rappresentando l'immagine del controllo che sto trascinando (col drag&drop), per avere un effetto ottico su quello che trascino...
la classe "CursorControl" (statica) contiene una funzione (CreateCursor) che accetta come parametri il controllo che si vuole traslare e la dimensione che deve avere il cursore (w,h) fornendo un cursore con l'immagine del controllo.
il cambio del cursore avviene dentro la sub Panel1_DragOver e viene riportato allo stato normale dentro Label1_GiveFeedback quando terminato (o quando non è possibile trascinare)
il codice potrebbe essere migliorato ad esempio aggiungendo un riferimentoi nell'immagine del cursore quando si preme ctrl (per distinguere da quando si copia).
codice:
Imports System.Reflection
Imports System.Runtime.InteropServices
Public Class Form1
Private Sub Panel1_DragDrop(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles Panel3.DragDrop, Panel2.DragDrop, Panel1.DragDrop, Panel4.DragDrop
Dim label As Label
Dim panel As Panel
Dim P As Point
'ricavo il panel destinatario della label
panel = DirectCast(sender, Panel)
'ricavo la label da copiare/spostare
label = DirectCast(e.Data.GetData(GetType(Label)), Label)
'ottengo la posizione del mouse relativa al pannello dove posizionerò la label
P = panel.PointToClient(New Point(e.X, e.Y))
'controllo se si tratta di copiare o spostare
label.BorderStyle = BorderStyle.None
If (e.Effect = DragDropEffects.Copy) Then
' è una copia, quindi creo una label uguale (vedi tu cosa esattamente copiare)
' in c# userei la reflection per ciclare e inpostare le proprieta senza fare 1 ad 1, ma in vb.net... fai tu...
Dim l As New Label
'aggiungo al gestore di eventi
'AddHandler l.MouseDown, AddressOf Label1_MouseDown
'ora ho cambiato, quelle copiate chiamano Label1_MouseMove e non più MouseDown
'(guarda nella sub per capire perchè
AddHandler l.MouseMove, AddressOf Label1_MouseMove
'continuo a settare proprietà...
l.AutoSize = label.AutoSize
l.BackColor = label.BackColor
l.Size = label.Size
l.Text = label.Text
l.Location = P
l.BorderStyle = BorderStyle.None
panel.Controls.Add(l)
Else
'si deve spostare, quindi la rimuovo dal contenitore dalla quale l'ho presa
label.Parent.Controls.Remove(label)
'imposto la nuova posizione
label.Location = P
'la aggiungo al nuovo contenitore
panel.Controls.Add(label)
End If
End Sub
Private Sub Panel1_DragOver(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles Panel3.DragOver, Panel2.DragOver, Panel1.DragOver, Panel4.DragOver
'quando passo trascinando una label su un panel viene richiamato questo metodo
'(prima di rilasciare il tasto del mouse)
'controllo se c'è ad esempio premuto il tasto ctrl
If (e.KeyState = 9) Then
'è premuto quindi si tratta di una copia e imposto l'effetto
e.Effect = DragDropEffects.Copy
Else
'non è premuto il tasto ctrl quindi si tratta di spostare
e.Effect = DragDropEffects.Move
End If
Cursor.Current = CursorControl.CreateCursor(Label1, Label1.Width, Label1.Height)
End Sub
Private Sub Label1_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Label1.MouseDown, Label2.MouseDown
Dim label As Label
'ottengo la label che devo trascinare
label = DirectCast(sender, Label)
label.BorderStyle = BorderStyle.Fixed3D
'inizio l'operazione di trascinamento dando come effetti possibili la copi e lo spostamento
'e passo la label (stabilirò prima del termine se copiarla o spostarla tramite il dragOver)
label.DoDragDrop(label, DragDropEffects.Copy OrElse DragDropEffects.Move)
End Sub
Private Sub Label1_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Label1.MouseMove
'quando muovi il mouse sopra la label (solo quelle copiate
'controllo che sia premuto il tasto sx del mouse
If e.Button = Windows.Forms.MouseButtons.Left Then
'è premuto il tasto sx del mouse
Dim label As Label
Dim p As Point
label = DirectCast(sender, Label)
'somma algebrica del punto della label con lo spostamento del mouse
p = New Point(label.Location + New Point(e.X, e.Y))
'faccio in modo che cambi solo la coordinata X riportando la Y al valore precedente
p.Y = label.Location.Y
'reimposto la posizione della label
label.Location = p
End If
End Sub
Private Sub Label1_GiveFeedback(ByVal sender As System.Object, ByVal e As System.Windows.Forms.GiveFeedbackEventArgs) Handles Label1.GiveFeedback
e.UseDefaultCursors = Not (e.Effect = DragDropEffects.Copy Or e.Effect = DragDropEffects.Move)
End Sub
End Class
'*********************************************************************
Public NotInheritable Class CursorControl
Private Sub New()
End Sub
Public Structure IconInfo
Public fIcon As Boolean
Public xHotspot As Integer
Public yHotspot As Integer
Public hbmMask As IntPtr
Public hbmColor As IntPtr
End Structure
<DllImport("user32.dll")> _
Public Shared Function CreateIconIndirect(ByRef icon As IconInfo) As IntPtr
End Function
<DllImport("user32.dll")> _
Public Shared Function GetIconInfo(ByVal hIcon As IntPtr, ByRef pIconInfo As IconInfo) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
Public Shared Function CreateCursor(ByVal control As Control, ByVal xHotSpot As Integer, ByVal yHotSpot As Integer) As Cursor
Dim result As Cursor = Nothing
Using bmp As New Bitmap(xHotSpot, yHotSpot)
control.DrawToBitmap(bmp, New Rectangle(0, 0, xHotSpot, yHotSpot))
Dim tmp As New IconInfo()
GetIconInfo(bmp.GetHicon(), tmp)
tmp.xHotspot = xHotSpot
tmp.yHotspot = yHotSpot
tmp.fIcon = False
result = New Cursor(CreateIconIndirect(tmp))
End Using
Return result
End Function
End Class
domando scusa alla comunità e ai sig. moderatori se ho fatto una cosa non gradita andando un po OT.
ma ho pensato che poteva essere utile 
EDIT :
dimenticavo... ATTENZIONE è SOLO UNA BOZZA