Pergunta

Existe uma maneira fácil de garantir que, depois de arrastar-e-soltar falha para completar, o evento MouseUp não é de comer e ignorado pelo framework?

Eu encontrei um post no blog, descrevendo um mecanismo de, mas envolve uma boa dose de manual de escrituração, incluindo sinalizadores de status, eventos MouseMove, manual do rato "deixar" de verificação, etc.tudo o que eu preferia não ter para implementar, se isso puder ser evitado.

Foi útil?

Solução

Recentemente, eu estava querendo colocar a funcionalidade de Arrastar e Soltar no meu projeto e eu não tinha me deparado com este problema, mas eu estava intrigado e queria ver se eu poderia vir acima com um método melhor do que o descrito na página vinculada.Espero que eu claramente entendido tudo o que você queria fazer, e no geral eu acho que conseguimos resolver o problema de uma forma muito mais elegante e simples de moda.

Em uma breve nota de lado, para problemas como este, seria ótimo se você fornecer algum código para que possamos ver exatamente o que é que você está tentando fazer.Digo isto apenas porque achei algumas coisas sobre o seu código em minha solução...então espero que seja muito perto.

Aqui está o código, que vou explicar abaixo:

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

}

Eu ter deixado de fora a maioria do código do designer, mas incluiu o Manipulador de Eventos link de código, então você pode ter certeza de que está vinculada ao que.No meu exemplo, o arrastar/soltar está ocorrendo entre os rótulos LabelDrag e LabelDrop.

A principal peça da minha solução é usar o QueryContinueDrag evento.Esse evento é acionado quando o teclado ou o mouse alterações de estado depois de DoDragDrop tem sido chamada no controle.Você já pode estar fazendo isso, mas é muito importante que você chamar o método DoDragDrop de controle que é a sua fonte e não o método associado com o formulário.Caso contrário QueryContinueDrag NÃO vai fogo!

Uma coisa a notar é que QueryContinueDrag realmente fogo quando você soltar o mouse sobre o controlo de lista pendente então, precisamos ter certeza de que nós permitimos isso.Isso é feito através da verificação de que a posição do Mouse (obtido com o Controle global.MousePosition propriedade) está dentro do LabelDrop controle de retângulo.Você deve também ter a certeza de converter-se MousePosition a um ponto em relação à Janela do Cliente com PointToClient como Controle.MousePosition retorna um ecrã relativo posição.

Assim, verificando que o mouse é não sobre o controlo de lista pendente e que o botão do mouse é agora até temos efetivamente capturado um evento MouseUp para a LabelDrag controle!:) Agora, você poderia fazer qualquer coisa de processamento que deseja fazer aqui, mas se você já tem o código que você está usando no evento MouseUp processador, isso não é eficiente.Então ligue seu evento MouseUp a partir daqui, passando os parâmetros necessários e MouseUp manipulador nunca vai saber a diferença.

Apenas uma observação, porém, como eu chamo DoDragDrop de dentro o evento MouseDown do manipulador no meu exemplo, este código deve nunca na verdade directa evento MouseUp para o fogo.Eu só colocar esse código em mostrar que é possível fazê-lo.

Espero que ajude!

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top