首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DoDragDrop和MouseUp

DoDragDrop和MouseUp
EN

Stack Overflow用户
提问于 2008-08-26 23:23:05
回答 1查看 17.7K关注 0票数 19

有没有一种简单的方法可以确保在拖放失败后,MouseUp事件不会被框架吞噬和忽略?

我找到了一篇描述one mechanism的博客文章,但它涉及大量的手动记账,包括状态标志、MouseMove事件、手动“鼠标离开”检查等,如果可以避免的话,我宁愿不要实现所有这些。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2008-08-27 14:00:12

我最近想在我的项目中加入拖放功能,但我没有遇到这个问题,但我很好奇,真的想看看我是否能想出一个比你链接的页面中描述的方法更好的方法。我希望我清楚地理解了你想要做的一切,总的来说,我认为我成功地以一种更加优雅和简单的方式解决了这个问题。

顺便说一句,对于这样的问题,如果你提供一些代码,我们就可以确切地看到你想要做的事情,那就太好了。我这么说只是因为我在我的solution...so中假设了一些关于你的代码的事情,希望它非常接近。

下面是代码,我将在下面解释:

代码语言:javascript
复制
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实际上会触发,所以我们需要确保考虑到这一点。这是通过检查鼠标位置(使用全局Control.MousePosition属性检索)是否在LabelDrop控件矩形内来处理的。您还必须确保使用PointToClient将MousePosition转换为相对于客户端窗口的点,因为Control.MousePosition会返回屏幕相对位置。

因此,通过检查鼠标是否不在拖放控件上,以及鼠标按钮是否已打开,我们已经有效地为LabelDrag控件捕获了一个MouseUp事件!:)现在,您可以在这里执行您想要执行的任何处理,但是如果您已经在MouseUp事件处理程序中使用了代码,那么效率就会很低。因此,只需从这里调用MouseUp事件,并将必要的参数传递给它,MouseUp处理程序就永远不会知道其中的区别。

但需要注意的是,由于我在示例中从MouseDown事件处理程序中调用了DoDragDrop,因此此代码实际上不应该触发直接的MouseUp事件。我只是将这些代码放在其中,以显示它是可以做到的。

希望这能有所帮助!

票数 24
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29177

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档