10

我们开发了一个数据库应用程序。用户要求一项新功能:将 blob 复制到剪贴板,以便 Windows 资源管理器可以将它们粘贴为新文件。一种解决方案是将 blob 保存到临时文件夹中,并将这些临时文件添加到剪贴板。

但我正在寻找更好的解决方案。是否可以在 Windows 资源管理器中挂钩粘贴操作并自己将 blob 保存到目标路径?

4

4 回答 4

13

I've never tried it but I think it is indeed possible. Please take a look at the MSDN Documentation for Shell Clipboard Formats. CFSTR_FILECONTENTS and CFSTR_FILEDESCRIPTOR are the formats you are likely supposed to handle.

Additionally, I found an article at Code Project which provides a demo program: How to drag a virtual file from your app into Windows Explorer.

Update: An example written in .NET:

于 2009-04-16T14:12:05.940 回答
7

来自 MSDN 文章处理 Shell 数据传输场景

  • 现有文件应以 CF_HDROP 格式提供。
  • 提供 CFSTR_FILECONTENTS/CFSTR_FILEDESCRIPTOR 格式的类文件数据。这种方法允许目标从数据对象创建文件,而无需了解任何有关底层数据存储的信息。您通常应该将数据呈现为 IStream 接口。这种数据传输机制比全局内存对象更灵活,并且使用更少的内存。

从 MSDN 阅读的另外两篇好文章是:

当我第一次开始使用剪贴板传输文件时,我打印了所有三篇文章并阅读了几遍。

处理接口可能非常复杂。我找到了两个很好的库来帮助解决这个问题。

Delphi的拖放组件套件。如果您在主页上向下滚动,您会看到一些常见问题解答很好阅读。下载中还有很多示例应用程序。我认为 AsyncSource 演示应该对您正在寻找的内容有所帮助。该套件是带有源代码的免费软件。代码似乎注释得很好。

我目前正在使用 Quasidata 的Transfer@Once组件。它不是免费的,但非常便宜。我最初使用 Transfer@Once 是因为当时它比拖放组件套件得到更好的支持。然而,这种情况已经发生了逆转。Transfer@Once 还不支持 Delphi 2009。当我开始移动我的应用程序时,我可能会切换组件。购买时包含 Transfer@Once 代码。就个人而言,我发现拖放代码更容易阅读和遵循。

于 2009-04-16T16:43:35.720 回答
5

我会说资源管理器自己复制到目标文件,所以没有办法直接写入目标文件。这是有道理的,因为源文件的名称只能来自将数据复制到剪贴板的应用程序,而不必是资源管理器。OTOH目标文件的名称实际上可能不同,因为相同名称的文件可能已经存在于目标文件夹中,并且只有资源管理器才能为目标文件创建修改后的名称(例如通过添加“副本”或添加“( 2)" 到基本文件名)。

您需要为 Windows 资源管理器提供剪贴板格式,以便它可以粘贴文件。标准剪贴板格式的文档表明CF_HDROP是正确的。使用这种剪贴板格式,您将提供源文件名列表,但这些文件当然需要存在,因此您需要将它们保存到光盘中。

不过,您可以尝试使该过程尽可能轻量级。通常,当用户将数据复制到剪贴板时,它会立即放在那里,无论它是否用于粘贴操作。对于您的应用程序,这意味着您每次都需要创建文件并将文件名列表放入剪贴板。但是,Windows 确实支持一种称为延迟渲染的模式,该模式正好用于这种情况。基本上,您只将一个空的数据存根放到剪贴板上,并且只有当另一个应用程序尝试访问数据时,才会从您的应用程序请求它。因此,您可以通过一种方式实现这一点,即只有当用户尝试将文件粘贴到资源管理器中时,您才会将它们保存到光盘并返回文件名列表。

于 2009-04-16T14:00:44.890 回答
1

It's been a while since I toyed with copy/paste, but I'm pretty sure you can do what you're suggesting (insert the blob as a new file into the clipboard).

I seem to remember that depending on how you add to the clipboard you can specify what sort of data you're copying. I think if you get that data type right, you'll be able to paste as though you'd copied from windows explorer.

I'll try and dig out some more details this evening if I have a chance (I don't have all my bookmarks here at work)...

[Edit] Have a look at the wxWidgets documentation on drag and drop. That was what I'd been working with and it gives some hints about data types.

What are you writing in? Delphi?

[Edit2] I think this may actually be a limitation of Windows(?). It might just be the wxWidgets documentation, but there's a suggestion that you only copy filenames rather than the files themselves. If that's the case, you're going to have to ue your original suggestion of creating a temp file first :-(

于 2009-04-16T12:43:28.023 回答