文件拖放事件处理程序中的MessageBox导致Windows资源管理器冻结

时间:2016-11-28 22:55:20

标签: c# .net wpf drag-and-drop

场景:为UI-Control启用了dragdrop的C#/ WPF应用程序。从Windows资源管理器拖动文件并将其放在UI-Control上时,会出现一个MessageBox。

问题:只要没有点击消息框(通过点击“确定”),Windows资源管理器就会被冻结,并且(可能)等待拖放事件返回。

问题:在显示MessageBox之前,有没有办法从等待中释放Windows资源管理器?那么“DragEventArgs”类的“Handled”属性呢?

代码:

 private void OnDrop_ButtonOpen(object sender, DragEventArgs e)
 {
   if (e.Data.GetDataPresent(DataFormats.FileDrop))
   {
     string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
     MessageBox.Show(files[0]);
   }
 }
PS:其他类似问题存在。但是,没有“过早”返回事件的解决方案。

1 个答案:

答案 0 :(得分:1)

如果我们看一下this documentation article about Drag and Drop operations,我们可以看到它说:

  

当用户启动拖放操作时,源会通过调用DoDragDrop来创建数据对象并启动拖动循环

因此源窗口现在停留在由DoDragDrop function启动的循环中。

当光标进入另一个窗口(称为目标窗口)时,DoDragDrop函数将调用目标窗口的DragEnterDragOver方法{ {1}}界面。

当您释放鼠标按钮以将数据放到目标窗口时,IDropTarget函数将调用DoDragDrop接口的Drop方法。如果我们继续阅读......

  

当目标完成数据对象后, 将从IDropTarget :: Drop 返回。系统 返回源的DoDragDrop调用 ,以通知源数据传输已完成。

...我们发现在目标窗口退出其IDropTarget方法之前,不会退出源窗口的DoDragDrop调用。

在.NET中调用IDropTarget::Drop方法时,它会引发IDropTarget::Drop事件。引发事件意味着它调用所有附加的DragDrop事件处理程序,并且因为这不是异步的,所以调用方法(DragDrop)将被阻塞,直到调用所有IDropTarget::Drop事件处理程序并且退出。

所以回答你的问题:不,你不能“过早地”回复它。它被每线程代码执行的标准逻辑阻止:一次一行。

您最好的选择是:

  1. 启动任务/显示消息框的新线程。您可能必须为此创建一个消息循环,但我不是百分百肯定。

  2. 创建您自己的消息框表单,并使用非模态调用DragDrop显示它。