拖入另一个进程
Posted
技术标签:
【中文标题】拖入另一个进程【英文标题】:drag into another process 【发布时间】:2011-01-03 10:25:13 【问题描述】:我正在尝试将一个项目拖到资源管理器中。
该项目应该导致文件下载,所以我使用了我在网上找到的一个示例来使用CustomDataObject
下载文件,当他实际需要流时调用一个事件,然后我的应用程序执行繁重的提升并执行下载。
它在类似的剪贴板操作中运行良好。
实际的文件下载也会导致我的应用程序中的一些 UI 发生变化。主要是在表单上更改的“工作”图标,以及出现错误时的弹出气球。
在剪贴板操作中,我只在需要时使用了InvokeRequired
和BeginInvoke
,以确保这些UI 更改发生在主线程上。在拖动操作中,UI 线程正在等待从DoDragDrop
返回,而由CustomDataObject
引发的事件正在另一个线程上调用。当我尝试调用BeginInvoke
或Invoke
时,UI 线程仍在等待,我无法完成删除。
在访问源应用程序的 UI 时,是否有关于如何允许跨应用程序拖放的示例或推荐的最佳实践?
更新
here 是 CodeProject 的原始文章,DataObjectEx
是我为自己修改的。我只是将GetFileContents
方法更改为调用一个虚拟方法,该方法返回一个包含从类继承的文件数据的Stream
,并重写该虚拟方法以从网络获取文件。
当我想在获取文件的同时更改 UI 中的内容时,问题就出现了。正如我之前所说 - 主 UI 线程仍然“卡在”DoDragDrop
方法调用中,因此我无法按时调用它来执行工作线程在下载文件之前和之后所需的 UI 更改。
【问题讨论】:
在您描述“CustomDataObject”是什么类型的动物以及它如何在您的应用程序中运行代码之前,我怀疑您会得到一个有用的答案。 我会深入挖掘,从网上找到我使用的代码示例 【参考方案1】:如果这是一个标准的 WinForms 应用程序,那么您真正需要在应用程序中做的就是在表单中为 DragEnter 和 DragDrop 添加事件处理程序。
在 DragEnter 中,您需要检查对象的类型以确保它是文件名:
private void MyForm_DragEnter(object sender, DragEventArgs e)
if (e.Data.GetDataPresent(DataFormats.FileDrop))
string[] files = e.Data.GetData(DataFormats.FileDrop) as string[];
if (files != null)
// Do additional checks here if needed, like check extensions
e.Effect = DragDropEffects.Copy;
return;
e.Effect = DragDropEffects.None;
然后在您的 DragDrop 处理程序中,我将简单地存储文件名,然后激活一个计时器。这允许 DragDrop 立即返回,以便在您对文件进行任何可能需要时间的处理时,其他应用程序(在您的示例中为 Windows 资源管理器)不会挂起。在 DragDrop 完成之前,拖动源不会返回。
private void MyForm_DragDrop(object sender, DragEventArgs e)
string[] files = e.Data.GetData(DataFormats.FileDrop) as string[];
if (files != null)
_filesToProcess.Text = files[0]; // Assuming this is declared at the Form level
// Schedule a timer to fire in a few miliseconds as a simple asynchronous method
_DragDropTimer.Interval = 50;
_DragDropTimer.Enabled = true;
_DragDropTimer.Start();
Activate(); // Activates the form and gives it focus
【讨论】:
【参考方案2】:我遇到了同样的问题,发现 System.Windows.Forms.Control.DoDragDrop 忽略了我的 Form 对 COM 的 IAsyncOperation 的实现,而是在内部使用了 WinForm 的 IDataObject 的 DataObject 实现。不幸的是,WinForm 的 DataObject 类没有实现 IAsyncOperation。
所以我使用了这个project的VirtualFileDataObject实现IAsyncOperation,IDataObject,调用VirtualFileDataObject.DoDragDrop而不是Control.DoDragDrop。我将 VirtualFileDataObject.FileDescriptor.StreamContents 设置为一个委托,我在其中调用 UI 线程以报告下载文件的进度。
【讨论】:
以上是关于拖入另一个进程的主要内容,如果未能解决你的问题,请参考以下文章
如何创建一个区域,将文件拖入其中,将 URI 添加到列表中?
bootstarp-fileinput上传 火狐防止拖入文件直接打开新页面