DoDragDrop和MouseUp [英] DoDragDrop and MouseUp

查看:143
本文介绍了DoDragDrop和MouseUp的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



有没有一个简单的方法来确保拖放完成后,MouseUp事件不被框架吃掉? >我发现一篇博客文章描述了一种机制,但它涉及大量的手动簿记,包括状态标志,MouseMove事件,手动鼠标离开检查等,如果可以避免的话,我宁可不必执行。

解决方案

我最近想在我的项目中放置拖放功能,我没有遇到这个问题,但我很感兴趣,真的想看看能否提供比您所链接的页面中描述的更好的方法。我希望我清楚地了解你想要做的一切,总体而言,我认为我以更优雅和简单的方式成功地解决了这个问题。



对于像这样的问题,如果您提供一些代码,那么我们可以准确地看到您正在尝试的是什么,这将是非常好的。我说这只是因为我在我的解决方案中假设了一些关于你的代码的事情,所以希望它很接近。



这里是我将在下面解释的代码:

  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重要 - 必须调用LabelDrag的DoDragDrop方法!
//调用Form的DoDragDrop不允许QueryContinueDrag触发!
((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)
{
//获取RectDed LabelDrop
Rectangle rect = new Rectangle(LabelDrop。位置,新大小(LabelDrop.Width,LabelDrop.Height));

//如果鼠标左键并且鼠标当前没有超过LabelDrop
if(Control.MouseButtons!= MouseButtons.Left&!rect.Contains(PointToClient( Control.MousePosition)))
{
//取消DragDrop Action
e.Action = DragAction.Cancel;
//手动启动MouseUp事件
LabelDrag_MouseUp(发件人,新的MouseEventArgs(Control.MouseButtons,0,Control.MousePosition.X,Control.MousePosition.Y,0));
}
}

}

我有省略了大部分的设计师代码,但包括了事件处理程序链接代码,所以你可以确定什么链接到什么。在我的例子中,标签LabelDrag和LabelDrop之间发生拖放。



我的解决方案的主要部分是使用QueryContinueDrag事件。当在该控件上调用DoDragDrop之后键盘或鼠标状态发生更改时,会触发该事件。您可能已经这样做了,但是您调用作为源的控件的DoDragDrop方法,而不是与该表单关联的方法非常重要。否则QueryContinueDrag将不会触发!



需要注意的是,当您在放置控件上释放鼠标时,QueryContinueDrag实际上将会触发,所以我们需要以确保我们允许。这通过检查鼠标位置(用全局Control.MousePosition属性检索)在LabelDrop控件矩形内部来处理。您还必须确保将MousePosition转换为相对于客户端窗口的点与PointToClient作为Control.MousePosition返回相对相对位置。



因此,通过检查鼠标是不是通过放置控件,并且鼠标按钮现在向上,我们已经有效地捕获了LabelDrag控件的MouseUp事件! :)现在,你可以在这里做任何你想要做的处理,但是如果你已经有了你在MouseUp事件处理程序中使用的代码,这是不高效的。所以只需从这里调用你的MouseUp事件,传递必要的参数,并且MouseUp处理程序就不会知道这个区别。



只是一个注释,正如我所说的DoDragDrop从我的示例中的 MouseDown事件处理程序中,此代码应该永远不会直接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?

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.

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.

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

}

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.

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!

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.

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.

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.

Hope that helps!

这篇关于DoDragDrop和MouseUp的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆