的DoDragDrop和MouseUpDoDragDrop、MouseUp

2023-09-04 02:05:19 作者:软甜啾

有没有一种简单的方法,以确保后拖拖放未能完成,MouseUp事件不是吃掉和框架忽视?

Is there an easy way to ensure that after a drag-and-drop fails to complete, the MouseUp event isn't eaten up and ignored by the framework?

我发现了一个博客帖子描述一种机制 ,但它涉及了大量手工记账,包括状态标志的MouseMove事件,手册鼠标离开检查等,所有这一切我宁可不要来实现,如果它是可以避免的。

I have found a blog post describing one mechanism, but it involves a good deal of manual bookkeeping, including status flags, MouseMove events, manual "mouse leave" checking, etc. all of which I would rather not have to implement if it can be avoided.

推荐答案

我最近想要把拖动并在我的项目拖放功能,并且我还没有碰到过这个问题,但我很感兴趣真想仿佛看到我能拿出一个比您链接到页面描述的更好的方法。我希望我清楚地知道你想要做的,总体来说,我觉得我成功地在一个更优雅和简约时尚解决问题的一切。

I was recently wanting to put Drag and Drop functionality in my project and I hadn't come across this issue, but I was intrigued and really wanted to see if I could come up with a better method than the one described in the page you linked to. I hope I clearly understood everything you wanted to do and overall I think I succeeded in solving the problem in a much more elegant and simple fashion.

在一个快速侧面说明,对于这样的问题,它会,如果你提供一些code,所以我们可以清楚地看到什么是你正在尝试做的是巨大的。我说,这不仅是因为我认为你的code在我的解决方案几件事...所以希望它是pretty的接近。

On a quick side note, for problems like this it would be great if you provide some code so we can see exactly what it is you are trying to do. I say this only because I assumed a few things about your code in my solution...so hopefully it's pretty close.

这里的code,我会在下面解释:

Here's the code, which I will explain below:

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

}

我已经离开了大部分的设计师code,但包括事件处理程序连接起来code,所以你可以知道什么是链接到什么。在我的例子,拖动/降标签LabelDrag和LabelDrop之间存在的。

I have left out most of the designer code, but included the Event Handler link up code so you can be sure what is linked to what. In my example, the drag/drop is occuring between the labels LabelDrag and LabelDrop.

主片我的解决方案是使用QueryContinueDrag事件。当的DoDragDrop后键盘或鼠标的状态变化被称为上控制该事件触发。您可能已经这样做,但你叫那是你的源泉,而不是与窗体关联的方法控制的DoDragDrop方法是非常重要的。否则QueryContinueDrag将不会触发!

The main piece of my solution is using the QueryContinueDrag event. This event fires when the keyboard or mouse state changes after DoDragDrop has been called on that control. You may already be doing this, but it is very important that you call the DoDragDrop method of the control that is your source and not the method associated with the form. Otherwise QueryContinueDrag will NOT fire!

有一点需要注意的是,当您松开鼠标的的下拉控制QueryContinueDrag实际上火灾的,所以我们需要确保我们允许的。这是通过检查该鼠标位置(检索与全球Control.MousePosition属性)是LabelDrop控制矩形的内部进行处理。你还必须确保MousePosition转换为相对于客户窗口与PointToClient一个点作为Control.MousePosition返回的相关画面的位置。

One thing to note is that QueryContinueDrag will actually fire when you release the mouse on the drop control so we need to make sure we allow for that. This is handled by checking that the Mouse position (retrieved with the global Control.MousePosition property) is inside of the LabelDrop control rectangle. You must also be sure to convert MousePosition to a point relative to the Client Window with PointToClient as Control.MousePosition returns a screen relative position.

因此​​,通过检查鼠标的没有的比降控制和鼠标按钮现在的了的我们已经有效地捕获mouseUp事件的LabelDrag控制! :)现在,你可能只是做任何处理,你想在这里做的,但如果你已经有code你是在MouseUp事件处理程序使用,这是效率不高。所以就叫从这里您MouseUp事件,它传递必要的参数和的MouseUp处理程序永远不会知道其中的差别。

So by checking that the mouse is not over the drop control and that the mouse button is now up we have effectively captured a MouseUp event for the LabelDrag control! :) Now, you could just do whatever processing you want to do here, but if you already have code you are using in the MouseUp event handler, this is not efficient. So just call your MouseUp event from here, passing it the necessary parameters and the MouseUp handler won't ever know the difference.

刚一说明,虽然,我称之为的DoDragDrop从的在的在我的例子,这code必须的永远的真正得到一个直接的MouseUp事件MouseDown事件处理程序火。我只是把那个code。在那里,以表明它是可以做到的。

Just a note though, as I call DoDragDrop from within the MouseDown event handler in my example, this code should never actually get a direct MouseUp event to fire. I just put that code in there to show that it is possible to do it.

希望帮助!

相关推荐