Domanda

Esiste un modo semplice per garantire che, dopo il mancato completamento del trascinamento della selezione, l'evento MouseUp non venga consumato e ignorato dal framework?

Ho trovato un post sul blog che descrive un meccanismo, ma implica una buona dose di contabilità manuale, inclusi flag di stato, eventi MouseMove, controllo manuale del "lasciare il mouse", ecc.tutte cose che preferirei non dover attuare se fosse possibile evitarle.

È stato utile?

Soluzione

Recentemente volevo inserire la funzionalità Drag and Drop nel mio progetto e non avevo riscontrato questo problema, ma ero incuriosito e volevo davvero vedere se potevo trovare un metodo migliore di quello descritto nella pagina che hai collegato A.Spero di aver capito bene tutto quello che volevi fare e nel complesso penso di essere riuscito a risolvere il problema in modo molto più elegante e semplice.

Una breve nota a margine: per problemi come questo sarebbe fantastico se fornissi del codice in modo che possiamo vedere esattamente cosa stai cercando di fare.Lo dico solo perché ho dato per scontato alcune cose sul tuo codice nella mia soluzione... quindi spero che sia abbastanza vicino.

Ecco il codice, che spiegherò di seguito:

this.LabelDrag.QueryContinueDrag += new System.Windows.Forms.QueryContinueDragEventHandler(this.LabelDrag_QueryContinueDrag);
this.LabelDrag.MouseDown += new System.Windows.Forms.MouseEventHandler(this.LabelDrag_MouseDown);
this.LabelDrag.MouseUp += new System.Windows.Forms.MouseEventHandler(this.LabelDrag_MouseUp);

this.LabelDrop.DragDrop += new System.Windows.Forms.DragEventHandler(this.LabelDrop_DragDrop);
this.LabelDrop.DragEnter += new System.Windows.Forms.DragEventHandler(this.LabelMain_DragEnter);

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void LabelDrop_DragDrop(object sender, DragEventArgs e)
    {
        LabelDrop.Text = e.Data.GetData(DataFormats.Text).ToString();
    }


    private void LabelMain_DragEnter(object sender, DragEventArgs e)
    {
        if (e.Data.GetDataPresent(DataFormats.Text))
            e.Effect = DragDropEffects.Copy;
        else
            e.Effect = DragDropEffects.None;

    }

    private void LabelDrag_MouseDown(object sender, MouseEventArgs e)
    {
        //EXTREMELY IMPORTANT - MUST CALL LabelDrag's DoDragDrop method!!
        //Calling the Form's DoDragDrop WILL NOT allow QueryContinueDrag to fire!
        ((Label)sender).DoDragDrop(TextMain.Text, DragDropEffects.Copy); 
    }

    private void LabelDrag_MouseUp(object sender, MouseEventArgs e)
    {
        LabelDrop.Text = "LabelDrag_MouseUp";
    }

    private void LabelDrag_QueryContinueDrag(object sender, QueryContinueDragEventArgs e)
    {
        //Get rect of LabelDrop
        Rectangle rect = new Rectangle(LabelDrop.Location, new Size(LabelDrop.Width, LabelDrop.Height));

        //If the left mouse button is up and the mouse is not currently over LabelDrop
        if (Control.MouseButtons != MouseButtons.Left && !rect.Contains(PointToClient(Control.MousePosition)))
        {
            //Cancel the DragDrop Action
            e.Action = DragAction.Cancel;
            //Manually fire the MouseUp event
            LabelDrag_MouseUp(sender, new MouseEventArgs(Control.MouseButtons, 0, Control.MousePosition.X, Control.MousePosition.Y, 0));
        }
    }

}

Ho tralasciato la maggior parte del codice del designer, ma ho incluso il codice di collegamento del gestore eventi in modo da poter essere sicuri di cosa è collegato a cosa.Nel mio esempio, il trascinamento avviene tra le etichette LabelDrag e LabelDrop.

La parte principale della mia soluzione utilizza l'evento QueryContinueDrag.Questo evento si attiva quando lo stato della tastiera o del mouse cambia dopo che DoDragDrop è stato chiamato su quel controllo.Potresti già farlo, ma è molto importante chiamare il metodo DoDragDrop del controllo che è la tua origine e non il metodo associato al modulo.Altrimenti QueryContinueDrag NON verrà attivato!

Una cosa da notare è che QueryContinueDrag verrà effettivamente attivato quando rilasci il mouse sul controllo di caduta quindi dobbiamo assicurarci di consentirlo.Questa operazione viene gestita verificando che la posizione del mouse (recuperata con la proprietà globale Control.MousePosition) sia all'interno del rettangolo di controllo LabelDrop.Devi anche assicurarti di convertire MousePosition in un punto relativo alla finestra client con PointToClient poiché Control.MousePosition restituisce un relativo allo schermo posizione.

Quindi controllando che il mouse sia non sopra il controllo di rilascio e che ora si trova il pulsante del mouse su abbiamo effettivamente catturato un evento MouseUp per il controllo LabelDrag!:) Ora, potresti semplicemente eseguire qualsiasi elaborazione desideri qui, ma se hai già il codice che stai utilizzando nel gestore di eventi MouseUp, questo non è efficiente.Quindi chiama semplicemente il tuo evento MouseUp da qui, passandogli i parametri necessari e il gestore MouseUp non noterà mai la differenza.

Solo una nota però, poiché chiamo DoDragDrop da entro il gestore dell'evento MouseDown nel mio esempio, questo codice dovrebbe Mai effettivamente ottenere l'attivazione diretta di un evento MouseUp.Ho semplicemente inserito quel codice per dimostrare che è possibile farlo.

Spero che aiuti!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top