Question

Existe-t-il un moyen simple de garantir qu'après l'échec d'un glisser-déposer, l'événement MouseUp n'est pas consommé et ignoré par le framework ?

J'ai trouvé un article de blog décrivant un mécanisme, mais cela implique une grande partie de la comptabilité manuelle, y compris les indicateurs d'état, les événements MouseMove, la vérification manuelle du « congé de la souris », etc.tout cela que je préférerais ne pas avoir à mettre en œuvre si cela peut être évité.

Était-ce utile?

La solution

Je voulais récemment intégrer la fonctionnalité Glisser-Déposer dans mon projet et je n'avais pas rencontré ce problème, mais j'étais intrigué et je voulais vraiment voir si je pouvais trouver une meilleure méthode que celle décrite dans la page que vous avez liée. à.J'espère avoir bien compris tout ce que vous vouliez faire et dans l'ensemble, je pense avoir réussi à résoudre le problème d'une manière beaucoup plus élégante et simple.

En passant, pour des problèmes comme celui-ci, ce serait bien si vous fournissez du code afin que nous puissions voir exactement ce que vous essayez de faire.Je dis cela uniquement parce que j'ai supposé quelques éléments concernant votre code dans ma solution... donc j'espère que c'est assez proche.

Voici le code, que je vais expliquer ci-dessous :

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));
        }
    }

}

J'ai laissé de côté la plupart du code du concepteur, mais j'ai inclus le code de liaison du gestionnaire d'événements afin que vous puissiez être sûr de ce qui est lié à quoi.Dans mon exemple, le glisser/déposer s'effectue entre les étiquettes LabelDrag et LabelDrop.

L'élément principal de ma solution consiste à utiliser l'événement QueryContinueDrag.Cet événement se déclenche lorsque l'état du clavier ou de la souris change après l'appel de DoDragDrop sur ce contrôle.Vous le faites peut-être déjà, mais il est très important que vous appeliez la méthode DoDragDrop du contrôle qui est votre source et non la méthode associée au formulaire.Sinon, QueryContinueDrag ne se déclenchera PAS !

Une chose à noter est que QueryContinueDrag se déclenchera lorsque vous relâcherez la souris. sur le contrôle de chute nous devons donc nous assurer de permettre cela.Ceci est géré en vérifiant que la position de la souris (récupérée avec la propriété globale Control.MousePosition) se trouve à l'intérieur du rectangle de contrôle LabelDrop.Vous devez également vous assurer de convertir MousePosition en un point relatif à la fenêtre client avec PointToClient car Control.MousePosition renvoie un écran relatif position.

Donc en vérifiant que la souris est pas sur le contrôle drop et que le bouton de la souris est maintenant en haut nous avons effectivement capturé un événement MouseUp pour le contrôle LabelDrag !:) Maintenant, vous pouvez simplement effectuer le traitement que vous souhaitez effectuer ici, mais si vous avez déjà du code que vous utilisez dans le gestionnaire d'événements MouseUp, cela n'est pas efficace.Il suffit donc d'appeler votre événement MouseUp à partir d'ici, en lui transmettant les paramètres nécessaires et le gestionnaire MouseUp ne fera jamais la différence.

Juste une note cependant, car j'appelle DoDragDrop depuis dans le gestionnaire d'événements MouseDown dans mon exemple, ce code devrait jamais en fait, déclenchez un événement MouseUp direct.Je viens de mettre ce code là-dedans pour montrer qu'il est possible de le faire.

J'espère que cela pourra aider!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top