.net - DoDragDrop和MouseUp

标签 .net winforms events drag-and-drop

有没有一种简单的方法来确保在拖放操作完成后,MouseUp事件不会被框架吃掉并忽略?

我已经找到了描述one mechanism的博客文章,但是涉及大量的手动记账,包括状态标志,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 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));
        }
    }

}


我省略了大多数设计器代码,但是包括了事件处理程序链接代码,因此您可以确定什么链接到什么。在我的示例中,拖放发生在标签LabelDrag和LabelDrop之间。

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

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

因此,通过检查鼠标不在放置控件上并且鼠标按钮现在处于向上状态,我们有效地捕获了LabelDrag控件的MouseUp事件! :)现在,您可以执行此处要执行的任何处理,但是如果您已经有在MouseUp事件处理程序中使用的代码,则效率不高。因此,只需从此处调用MouseUp事件,并向其传递必要的参数,MouseUp处理程序将永远不会知道两者之间的区别。

不过,请注意,在我的示例中从MouseDown事件处理程序中调用DoDragDrop时,此代码实际上永远不会触发直接的MouseUp事件。我只是将代码放在那里,以表明有可能做到这一点。

希望有帮助!

关于.net - DoDragDrop和MouseUp,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29177/

相关文章:

vb.net - 从日期/时间 vb.net 中删除时间

c++ - SDL_event 列表变得又长又乱?

jQuery (ui) 解除事件绑定(bind)的一般方法?

c# - 查找未使用的功能?

c# - 创建更加用户友好的显示。我的想法,可能吗?

c# - Windows 窗体的 MVP 示例

asp.net - ASP.NET 是否使用反射来检查事件处理程序是否存在?

.net - System.Windows.Forms.WebBrowser : force X86?

c# - C#中唯一的字符串集

c# - WCF - 返回大图像 - 你的经验和技巧