Pregunta

¿Existe una manera fácil de garantizar que después de que no se complete un proceso de arrastrar y soltar, el marco no devore ni ignore el evento MouseUp?

Encontré una publicación de blog que describe un mecanismo, pero implica una gran cantidad de contabilidad manual, incluidos indicadores de estado, eventos MouseMove, verificación manual de "salida del mouse", etc.todo lo cual preferiría no tener que implementar si se puede evitar.

¿Fue útil?

Solución

Recientemente quería incluir la funcionalidad de arrastrar y soltar en mi proyecto y no me había encontrado con este problema, pero estaba intrigado y realmente quería ver si podía encontrar un método mejor que el descrito en la página que vinculó. a.Espero haber entendido claramente todo lo que querías hacer y, en general, creo que logré resolver el problema de una manera mucho más elegante y sencilla.

En una nota al margen, para problemas como este sería fantástico si proporcionara algún código para que podamos ver exactamente qué es lo que está intentando hacer.Digo esto sólo porque asumí algunas cosas sobre su código en mi solución... así que espero que sea bastante parecido.

Aquí está el código, que explicaré a continuación:

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

}

He omitido la mayor parte del código del diseñador, pero he incluido el código de enlace del controlador de eventos para que pueda estar seguro de qué está vinculado a qué.En mi ejemplo, el proceso de arrastrar y soltar se produce entre las etiquetas LabelDrag y LabelDrop.

La parte principal de mi solución es utilizar el evento QueryContinueDrag.Este evento se activa cuando el estado del teclado o del mouse cambia después de que se haya llamado a DoDragDrop en ese control.Quizás ya estés haciendo esto, pero es muy importante que llames al método DoDragDrop del control que es tu fuente y no al método asociado con el formulario.De lo contrario, ¡QueryContinueDrag NO se activará!

Una cosa a tener en cuenta es que QueryContinueDrag se activará cuando sueltes el mouse. en el control de caída así que debemos asegurarnos de permitirlo.Esto se maneja verificando que la posición del mouse (recuperada con la propiedad global Control.MousePosition) esté dentro del rectángulo de control LabelDrop.También debe asegurarse de convertir MousePosition a un punto relativo a la ventana del cliente con PointToClient ya que Control.MousePosition devuelve un relativo a la pantalla posición.

Entonces, al verificar que el mouse esté no sobre el control de colocación y que el botón del mouse ahora está arriba ¡Hemos capturado efectivamente un evento MouseUp para el control LabelDrag!:) Ahora, podrías hacer cualquier procesamiento que quieras hacer aquí, pero si ya tienes el código que estás usando en el controlador de eventos MouseUp, esto no es eficiente.Así que simplemente llame a su evento MouseUp desde aquí, pasándole los parámetros necesarios y el controlador MouseUp nunca notará la diferencia.

Sólo una nota, ya que llamo a DoDragDrop desde dentro el controlador de eventos MouseDown en mi ejemplo, este código debería nunca en realidad consigue que se active un evento MouseUp directo.Simplemente puse ese código allí para mostrar que es posible hacerlo.

¡Espero que ayude!

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top