Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you copy arbitrary data to the clipboard as a file?

We develop a database application. The user asks for a new feature: Copy blobs into the clipboard such that Windows Explorer can paste them as new files. One solution is to save the blobs into a temporary folder and add these temporary files to the clipboard.

But I'm looking for a better solution. Is it possible to hook the paste action in Windows Explorer and save the blobs to the destination path by myself?

like image 562
Francois Zbinden Avatar asked Apr 16 '09 11:04

Francois Zbinden


4 Answers

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:

  • Creating something from nothing
  • Creating something from nothing, asynchronously
like image 76
Rômulo Ceccon Avatar answered Oct 20 '22 10:10

Rômulo Ceccon


From the MSDN article Handling Shell Data Transfer Scenarios

  • Existing files should be offered with the CF_HDROP format.
  • Offer file-like data with CFSTR_FILECONTENTS/CFSTR_FILEDESCRIPTOR formats. This approach allows the target to create a file from a data object without needing to know anything about the underlying data storage. You should normally present the data as an IStream interface. This data transfer mechanism is more flexible than a global memory object and uses much less memory.

Two other good articles to read from MSDN are:

  • Shell Data Object
  • Shell Clipboard Formats

When I first started working on using the clipboard to transfer files I printed off all three articles and read them several times.

Dealing with the interfaces can be quite involved. I have found two good libraries out there to help with this.

The The Drag and Drop Component Suite for Delphi. If you scroll down on the home page you will see some FAQs are good reading. There are also a lot of sample applications with the download. I think the AsyncSource demos should be helpful for what you are looking for. The suite is freeware with source. The code seems to be well commented.

I am currently using the Transfer@Once component from Quasidata. It is not free but is very inexpensive. I initially used Transfer@Once because at the time it was better supported than the Drag and Drop component suite. However, that situation has reversed itself. Transfer@Once does not yet support Delphi 2009. When I get around to moving my application I will probably switch components. The Transfer@Once code is included with purchase. Personally I found the Drag and Drop code to be much easier to read and follow.

like image 44
Mark Elder Avatar answered Oct 20 '22 11:10

Mark Elder


I'd say that explorer does the copying to the destination files itself, so there's no way to directly write the destination files. This makes sense, because the names of the source files can only come from the application that copied the data to the clipboard, which need not be explorer. OTOH the names of the destination files may actually differ, because files of the same name could already exist in the destination folder, and only explorer can create the modified names for the destination files (like by prepending "Copy of " or by appending " (2)" to the base file name).

You will need to provide the clipboard format for the Windows Explorer so that it can paste the files. The documentation of standard clipboard formats suggests that CF_HDROP is the right one. With this clipboard format you would provide a list of source file names, but the files do need to exist of course, so you will need to save them to disc.

You could try to make the process as light-weight as possible, though. Usually when a user copies data to the clipboard it is put there immediately, whether or not it will be used for a paste operation. For your application that would mean that you would need to create the files and put the list of file names into the clipboard, every time. However, Windows does support a mode called Delayed Rendering, which is used exactly for such cases. Basically you put only an empty stub of the data onto the clipboard, and only when another application tries to access the data it will be requested from your app. So you could implement this in a way that only when the user tries to paste the files into explorer you would save them to disc and return the list of file names.

like image 39
mghie Avatar answered Oct 20 '22 11:10

mghie


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 :-(

like image 24
Jon Cage Avatar answered Oct 20 '22 11:10

Jon Cage