winforms DoDragDrop 和 MouseUp
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29177/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
DoDragDrop and MouseUp
提问by Chris Ammerman
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?
有没有一种简单的方法可以确保在拖放操作失败后,MouseUp 事件不会被框架吃掉和忽略?
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.
我找到了一篇描述一种机制的博客文章,但它涉及大量手动簿记,包括状态标志、MouseMove 事件、手动“鼠标离开”检查等。如果可以的话,我宁愿不必实施所有这些避免了。
回答by Adam Haile
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.
我省略了大部分设计器代码,但包含了事件处理程序链接代码,因此您可以确定哪些内容与哪些内容相关联。在我的示例中,拖/放发生在标签 LabelDrag 和 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!
我的解决方案的主要部分是使用 QueryContinueDrag 事件。当在该控件上调用 DoDragDrop 后键盘或鼠标状态发生更改时,将触发此事件。您可能已经这样做了,但是调用作为源的控件的 DoDragDrop 方法而不是与表单关联的方法非常重要。否则 QueryContinueDrag 不会触发!
One thing to note is that QueryContinueDrag will actually fire when you release the mouse on the drop controlso 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 relativeposition.
需要注意的一件事是,当您在放置控件上释放鼠标时,QueryContinueDrag 实际上会触发,因此我们需要确保允许这样做。这是通过检查鼠标位置(使用全局 Control.MousePosition 属性检索)是否在 LabelDrop 控件矩形内来处理的。您还必须确保使用 PointToClient 将 MousePosition 转换为相对于客户端窗口的点,因为 Control.MousePosition 返回屏幕相对位置。
So by checking that the mouse is notover the drop control and that the mouse button is now upwe 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.
因此,通过检查鼠标是否未在放置控件上并且鼠标按钮现在已按下,我们已经有效地为 LabelDrag 控件捕获了一个 MouseUp 事件!:) 现在,您可以在此处进行任何您想做的处理,但是如果您已经拥有在 MouseUp 事件处理程序中使用的代码,则这效率不高。因此,只需从此处调用 MouseUp 事件,将必要的参数传递给它,MouseUp 处理程序就永远不会知道其中的区别。
Just a note though, as I call DoDragDrop from withinthe MouseDown event handler in my example, this code should neveractually get a direct MouseUp event to fire. I just put that code in there to show that it is possible to do it.
只是注意,虽然,我称之为的DoDragDrop从内部在我的例子MouseDown事件处理程序,此代码应从未真正得到一个直接的MouseUp事件火灾。我只是把那个代码放在那里来表明它是可能的。
Hope that helps!
希望有帮助!

