Pagina 2 di 3 primaprima 1 2 3 ultimoultimo
Visualizzazione dei risultati da 11 a 20 su 25
  1. #11

    DragAndDrop, posizionamento, spostamento, eliminazione

    questo codice replica (a grandi linee ) la modalità di drag and drop come in progettazione di VS ( ed è quello che interesserà a me per simulare una mappa con puntelli personalizzati, button, label e forse anche combobox, etc..)

    nel form ci devono essere due Panel : Panel1 e Panel 2
    in Panel1 (contenitore d'origine) aggiungere i controlli da droppare (è possibile anche a runtime)
    Panel2, è il contenitore di destinazione

    tutti i controlli in Panel1 (anche quelli aggiunti a Runtime) verranno automaticamete abilitati al drop per il Panel2 e potranno essere:
    1.posizionati
    2 riposizionati o eliminati dal panel2, premento il Tasto CTRL

    altro leggere note nel codice:

    COPIA E INCOLLA NELLA CLASSE DEL FORM, questo
    codice:
    Public Class Form1
        ' NOTE
        ' tutti i controlli contenuti in panel1 sono abilitati al drag and drop.
        ' il Panel2 è il contenitore di destinazione
        '  nel Metodo "AbleDraggInOggetto" (SELCT CASE..)  sono elenacati i tipi di controlli 
        ' che potranno  essere droppati.
        ' è possibile posizionare l'oggetto anche in un secondo momento 
        ' tramite il tasto CTRL attiva / disattiva lo spostamento dell'oggetto nel suo contenitore,
        ' se viene spostato fuori dal contenotire (panel2) l'oggetto verrà eliminato
        ' per abilitare al drop, altri tipi di cotrolli , devono essere specificati nel Metodo "AbleDraggInOggetto"
        ' nella struttura del SELEC CASE.... aggiungendo il CASE per il tipo del controllo (anche s'è annidato)
    
    
        Private m_MouseIsDown As Boolean = False, DragOggetto As Control = Nothing, Dragged As Boolean = False,
              _TypesOggettiDragging As New List(Of Type)
    
         ' visualizza/nascode il popup
        Private Property Sposta As Boolean
            Get
                Return Me.Controls("Popup_ATTIVA").Visible
            End Get
            Set(ByVal value As Boolean)
                Me.Controls("Popup_ATTIVA").Visible = value
            End Set
        End Property
    
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Me.KeyPreview = True
    
            With Panel2 ' riferito al contenitore da abilitare al DRAG and Drop
                ' ABILITA il pannello al DRAG and DROP
                .AllowDrop = True
                ' e ne assegna tutti gli eventi per il drag and drop
                AddHandler .DragDrop, AddressOf Contenitore_DragDrop
                AddHandler .DragEnter, AddressOf Contenitore_DragEnter
                AddHandler .DragLeave, AddressOf Contenitore_DragLeave
                AddHandler .DragOver, AddressOf Contenitore_DragOver
            End With
    
            ' ABILITA AL Trascinamento tutti gli oggetti contenuti IN PANEL1
            'questo Handler è stato aggiunto nel codice della calsse del form
            'da modalità di progettazione (su trova nel metodo seguente, già associato all'evento)
            'AddHandler Panel1.ControlAdded, AddressOf Contenitore_ControlAdded
    
    
            ' Visualizza popup quando attiva la modalità di riposizinamento o eliminazione
            Dim Popup As New Label
            With Popup
                .Name = "Popup_ATTIVA"
                .Text = "Modalità Spostamento o elimina.."
                .AutoSize = True
                .BackColor = Color.White
                .Anchor = AnchorStyles.Right Or AnchorStyles.Top
                .Hide()
                Me.Controls.Add(Popup)
                .Location = New Point(Panel2.Left + (Panel2.Width - .Width), Panel2.Top)
                .BringToFront()
            End With
    
        End Sub
    
        Private Sub Contenitore_ControlAdded(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ControlEventArgs) Handles Panel1.ControlAdded
            Dim Ctrl As Control = e.Control
            AddHandler Ctrl.MouseDown, AddressOf CopyOggetto_MouseDown
            AddHandler Ctrl.MouseMove, AddressOf CopyOggetto_MouseMove
            If Not _TypesOggettiDragging.Contains(Ctrl.GetType) Then _TypesOggettiDragging.Add(Ctrl.GetType)
        End Sub
    
        Private Function GetMousePosition_IntoControl(ByVal Ctrl As Control) As Point
            Dim MousePos As New Point(Control.MousePosition)
            Do While Ctrl IsNot Nothing
                With Ctrl
                    MousePos = Point.Subtract(MousePos, .Location)
                    MousePos = Point.Subtract(MousePos, New Point(.Width - .ClientSize.Width, .Height - .ClientSize.Height))
                    Ctrl = .Parent
                End With
            Loop
            Return MousePos
        End Function
    
        Private Function AbleDraggInOggetto(ByVal Oggetto As Control) As Control
            Dim NewObJect As New Control
    
            ' istanzio il nuovo oggetto asseconda del tipo origine
            ' se non presente in questo elenco, NON SARA' POSSIBILE il drag and drog
            Select Case Oggetto.GetType
                Case GetType(Label)
                    NewObJect = New Label
                Case GetType(LinkLabel)
                    NewObJect = New LinkLabel
                Case GetType(Button)
                    NewObJect = New Button
                Case GetType(TextBox)
                    NewObJect = New TextBox
                Case GetType(CheckBox)
                    NewObJect = New CheckBox
                Case GetType(FlowLayoutPanel)
                    NewObJect = New FlowLayoutPanel
                Case GetType(ComboBox)
                    NewObJect = New ComboBox
                Case Else
                    NewObJect = New Control
            End Select
    
            With NewObJect
                .Hide()
                .Location = Oggetto.Location
                .Text = Oggetto.Text
                .Size = Oggetto.Size
                .Font = Oggetto.Font
                .Enabled = False
    
                'ricorsione per tutti i controlli figli, se presenti
                For Each Ctrl As Control In Oggetto.Controls
                    Dim N As Control = AbleDraggInOggetto(Ctrl)
                    .Controls.Add(N)
                    N.Show()
                    N.BringToFront()
                    N.Enabled = True
                Next
    
            End With
    
            DragOggetto = NewObJect
            Return NewObJect
        End Function
    
        Private Function EnabledDraggInOggetto(ByVal Ctrl As Control) As Boolean
            Return _TypesOggettiDragging.Contains(Ctrl.GetType)
        End Function
    
    
    
        Private Sub CopyOggetto_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs)
            m_MouseIsDown = True
        End Sub
    
        Private Sub CopyOggetto_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs)
            If m_MouseIsDown Then
                Dragged = False
                ' Initiate dragging and allow either copy
                With AbleDraggInOggetto(sender)
                    Me.Controls.Add(DragOggetto)
                    .BringToFront()
                    sender.DoDragDrop(DragOggetto, DragDropEffects.Copy)
                    If Not Dragged Then .Dispose()
                End With
            End If
            m_MouseIsDown = False
        End Sub
    
    
    
        Private Sub MoveOggetto_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs)
    
            If m_MouseIsDown And Sposta Then
                Dragged = False
                ' Initiate dragging and allow either move.
                DragOggetto = sender
                With DragOggetto
                    .Enabled = False
                    Me.Controls.Add(DragOggetto)
                    .BringToFront()
    
                    sender.DoDragDrop(DragOggetto, DragDropEffects.Move)
                    If Not Dragged Then .Dispose()
                End With
            End If
            m_MouseIsDown = False
        End Sub
    
        Private Sub Contenitore_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles Panel2.DragDrop
    
            Dim NewOggetto As Control = e.Data.GetData(DragOggetto.GetType)
            sender.Controls.Add(NewOggetto)
            With NewOggetto
                .Location = Me.GetMousePosition_IntoControl(sender)
                .Enabled = True
                .BringToFront()
                AddHandler .MouseDown, AddressOf CopyOggetto_MouseDown
                AddHandler .MouseMove, AddressOf MoveOggetto_MouseMove
    
            End With
    
            Dragged = True
    
        End Sub
    
        Private Sub Contenitore_DragEnter(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles Panel2.DragEnter
            If EnabledDraggInOggetto(DragOggetto) Then 'e.Data.GetDataPresent(GetType(Label)) Then
    
                e.Effect = DragDropEffects.Copy Or DragDropEffects.Move Or DragDropEffects.Scroll
    
            Else
                e.Effect = DragDropEffects.None
            End If
        End Sub
    
        Private Sub Contenitore_DragOver(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles Panel2.DragOver
            DragOggetto.Show()
            DragOggetto.Location = Me.GetMousePosition_IntoControl(Me)
        End Sub
    
        Private Sub Contenitore_DragLeave(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Panel2.DragLeave
            DragOggetto.Hide()
        End Sub
    
    
    
        Private Sub Form1_KeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown
            If e.Control Then Sposta = Not Sposta
        End Sub
    
    
    End Class

    è da renderlo più efficente, magari saper come copiare esattamente un oggetto (con tutte le sue proprietà) e come creare automaticamente e dinamicamente un nuovo oggetto di ogni tipo, sostituendo la parte di codice del SELECT CASE....


    EDIT: aggiunta la proprietà SPOSTA che visualizza o nasconde il popup per la modalità Riposizionamento o elimina..
    Michele

  2. #12
    da studiare..!!!



    ps: forse c'è un ' in più nel caricamento del form su 'AddHandler Panel1.ControlAdded, AddressOf Contenitore_ControlAdded


    Grazie Michele

  3. #13
    si infatti, quella è una nota, è tra apici

    oramai sono partito con la faccenda...
    Michele

  4. #14
    ciao..

    sono tornato dopo un bel mese di ferie dove non ho visto computer e codice. Riaprendo il mio programmino mi sono subito scontrato con un problema che richiederà una consulenza del forum visto che non ne riesco a venire a capo. Ricalcando i consigli di Michele, sono riuscito a fare la mia bella operazione di drag and drop con il seguente codice

    codice:
    Private Sub timetable1_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs)
            Dim OrigineOggetto As Control = e.Data.GetData(GetType(Label))
            Dim NewOggetto As New Label
    
    
            With NewOggetto
                ' qua assegni le proprietà che ti interessano che vengano copiate per la nuova label
                .Text = OrigineOggetto.Text
                .Size = OrigineOggetto.Size
                .BackColor = OrigineOggetto.BackColor
                .BorderStyle = BorderStyle.FixedSingle
                .Location = Me.GetMousePosition_IntoControl(sender)
                sender.Controls.Add(NewOggetto)
                .BringToFront()
                .AllowDrop = True
            End With
    
            AddHandler NewOggetto.MouseDown, AddressOf sposta_MouseDown
            AddHandler NewOggetto.MouseMove, AddressOf sposta_MouseMove
            'AddHandler .MouseLeave, AddressOf sposta_Mouseleave
    
        End Sub
    
    
        Private Sub sposta_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
    
            'sender.Font = New Font(Me.Font, FontStyle.Bold)
            'sender.borderstyle = BorderStyle.Fixed3D
    
    
            If e.Button = MouseButtons.Left Then
                sender.Left = sender.Left + (e.X - memx)
    
            End If
    
        End Sub
    
    
    
        Private Sub sposta_Mouseleave(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
    
            sender.borderstyle = BorderStyle.None
    
    
        End Sub
    
    
    
        Private Sub sposta_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
    
            If e.Button = MouseButtons.Left Then
                memx = e.X
                memy = e.Y
            Else
                Return
            End If
    
        End Sub
    
    
    
    
        Private Sub timetable1_DragEnter(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DragEventArgs)
    
            If e.Data.GetData(GetType(Label)) IsNot Nothing Then
                e.Effect = DragDropEffects.Move
            Else
                e.Effect = DragDropEffects.None
            End If
    
        End Sub
    dove timetable1 è un usercontrol abilitato al drag and drop. In sostanza io trasporto una label su timetable, e una volta copiata (NewOggwtto) qui la vorrei spostare.. e ci riesco pure solo che resta una copia della label li dove è stata rilasciata; come se spostassi una copia della copia. Io vorrei invece trascinare la label e poi spostare quella..

    Spero che mi possiate aiutare!

  5. #15
    Utente di HTML.it L'avatar di U235
    Registrato dal
    Mar 2006
    Messaggi
    1,536
    ciao, io vorrei proporti un metodo un po diverso, vedi tu se ti sembra più facile e pulito.

    il codice è commentato, e se non riesci ad adattarlo alle tue esigenze domanda pure.

    si tratta di un esempio con tanti panel quanti ne vuoi (puoi semplicemente aggiungerli in maniera visuale), si tratta di gestione di eventi dinamici, idem per le label.
    quando trascini una label (ovviamente questa deve avere impostato l'evento MouseDown su Label1_MouseDown) questa chiama Label1_MouseDown che determina quale label si voglia trascinare, una volta stabilito, muovendo il mouse sopra un qualsiasi pannello (ovviamente questo deve avere impostato l'evento DragOver su Panel1_DragOver), si scatena l'evento Panel1_DragOver, questo determina se sia premuto il tasto ctrl, se si, allora si vuole fare una copia e di conseguenza aggiunge un + al cursore. una volta rilasciato il tasto del mouse (su un qualsiasi pannello, anche lo stesso) viene chiamato Panel1_DragDrop (sempre se... come sopra ma con DragDrop ) a questo punto non rimane che controllare se il cursore è per la copia o per lo spostamento, rimuovere eventualmente dal contenuitore padre la label ed aggiungerla al nuovo contenitore.
    purtroppo io in vb.net sono una chiavica (scrivo in c#) quindi mi scuso se ho usato una sintassi un po... così...
    ecco il codice :
    codice:
    Public Class Form1
    
        Private Sub Panel1_DragDrop(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles Panel4.DragDrop, Panel3.DragDrop, Panel2.DragDrop, Panel1.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
            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
                
                'continuo a settare proprietà...
                l.AutoSize = label.AutoSize
                l.BackColor = label.BackColor
                l.Size = label.Size
                l.Text = label.Text
                l.Location = P
                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 Panel4.DragOver, Panel3.DragOver, Panel2.DragOver, Panel1.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
        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)
            '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
    End Class
    qui il progetto completo.

    fammi sapere magari anche se ti fa schifo!

  6. #16
    .. e meno male che sei una chiavica a programmare in vb... In c che fai, programmi per la nasa?

    Ti ringrazio davvero per il tuo consiglio.
    si.. la tua soluzione è di certo più pulita, e se non ti rompe ti farò un po di domande a riguardo.


    La prima che viene cosi, senza aver applicato fisicamente ancora la tua soluzione al mio progetto, è che, una volta sposta la label in un panel, mi serve di poterla trascinare in orizzontale come oggetto fisico vero e proprio, quindi mantenendola visibile (la chiave di tutto è che l'informazione ricercata dall'utente e data dalla posizione fisica dove è rilasciato l'oggetto) ecco perché ho inserito il gestore di eventi mouse move sul nuovo oggetto. Credo (ma ti ripeto ancora non ho riportato il tuo metodo sul mio prg) che se applico questo gestore di eventi sulla tua soluzione il problema che si sposta una sorta di copia dell'oggetto resterebbe.. spero di essermi spiegato. E' come se avessi un mattoncino lego (che sarebbe il label appena spostato) che posso spostare a destra o a sinistra.. il mio prob è che cosi facendo, con la funzione sposta_mousemove, sposto il mattoncino lego, ma come nel fantastico mondo della fisica quantistica, oltre a spostarsi resta anche fermo li dove non dovrebbe più essere..

    perdonami. ma sono tornato da poco a lavoro e ancora rimpiango il mare!!

  7. #17
    Utente di HTML.it L'avatar di U235
    Registrato dal
    Mar 2006
    Messaggi
    1,536
    ciao,
    ricapitoliamo :

    da un panel prendi la label (la copi, quindi nel primo rimane giusto?), la trascini nel secondo panel, dove una volta posizionata vorresti spostarla fisicamente (all'interno del pannello 2), ma senza il drag&drop (proprio cambiare di posizione), giusto?

    EDIT :
    nella soluzione che ti ho postato, lo spostamento avviene senza premere ctrl, quindi in teoria, se tu prima la posizioni in un panel premendo ctrl (quindi la copi), successivamente hai la possibilità di spostarla dentro il secondo panel senza premere ctrl (sposti), l'unico inconveniente sarebbe che fintanto che non lasci il tasto del mouse quella rimane ferma dove si trova. invece tu vorresti vederla mentre si trascina e non vederla ferma (così mi sembra di capire).

    in questo caso le soluzioni possibili sono diverse, e direi anche addizionabili!

    caso A)
    al trascinammento, cambi il cursore con l'immagine del controllo fino al rilascio del mouse (poi ti spiego come), però ancora la label rimane ferma fino al rilascio del tasto del mouse, e vedresti il cursore che è diventato la label (quindi doppio fino al rilascio).

    caso B)
    una volta copiata la label nel panel2, usi una tecnica di trascinamento della label tramite il paint del panel2 (quindi in realtà non trascini più la label, ma la riscrivi nel graphics del panel2). questo caso va bene se devi ad esempio mandare in stampa il graphic del panel2

    caso C)
    come caso B con la differenza che sposti la label agendo su location di essa.

  8. #18
    Utente di HTML.it L'avatar di U235
    Registrato dal
    Mar 2006
    Messaggi
    1,536
    Siccome oggi mi sto annoiando (e non poco ) ho riletto il tuo ultimo post, e mi sono convinto che quello che volevi era una cosa del genere :

    codice:
    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
        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
    
    End Class
    in realtà ho modificato poco e niente dal precedente, le uniche cose sono che ora le label copiate (solo loro) non possiedono il drag&drop, ma solo lo spostamento (solo orizzontale) nel loro pannello (nella quale una volta messe non possono più uscire).

    non c'è molto da spiegare sul codice (credo che il commento su esso basti), ma se hai bisogno...

  9. #19
    Utente di HTML.it L'avatar di U235
    Registrato dal
    Mar 2006
    Messaggi
    1,536
    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

  10. #20
    BINGO... !!

    Grazie mille U235..

    Me aspetta.. fammi capire.

    Rispetto al mio codice (si lo vedo che è antico e quasi demenziale rispetto al tuo ) il problema risiedeva nel fatto che non aggiungevo questo:

    label = DirectCast(sender, Label)

    ??

    No, perchè ho provato e ancora resta l'ogetto origine..

    ora devo capire..


    Originariamente inviato da U235
    Siccome oggi mi sto annoiando (e non poco ) ho riletto il tuo ultimo post, e mi sono convinto che quello che volevi era una cosa del genere :

    codice:
    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
        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
    
    End Class
    in realtà ho modificato poco e niente dal precedente, le uniche cose sono che ora le label copiate (solo loro) non possiedono il drag&drop, ma solo lo spostamento (solo orizzontale) nel loro pannello (nella quale una volta messe non possono più uscire).

    non c'è molto da spiegare sul codice (credo che il commento su esso basti), ma se hai bisogno...

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.