Current version

v1.10.4 (stable)

Navigation

Main page
Archived news
Downloads
Documentation
   Capture
   Compiling
   Processing
   Crashes
Features
Filters
Plugin SDK
Knowledge base
Contact info
 
Other projects
   Altirra

Archives

Blog Archive

Drag-and-drop RTFM... no dice.

Either I need a better collection of books, or I have a habit of hitting weird problems.

I've been experimenting with drag-and-drop between an application and the Windows shell, and managed to get virtual objects dragging to the shell working without too much trouble. However, the opposite direction -- dragging from the shell to the application -- is refusing to work. I've been trying to accept the CFSTR_FILEDESCRIPTOR / CFSTR_FILECONTENTS pair of formats, and was scratching my head trying to figure out why IDataObject::QueryGetData() kept succeeding, but IDataObject::GetData() with the same format request kept failing. As usual, the Platform SDK documentation has shown to be a bit less than truthful and I've had to fill in bits from more reputable sources (i.e. The Old New Thing) and then just plain experimentation.

The first case that was giving me problems was the plain file drop case, until I figured out two things. The first was that I was looking for the wrong clipboard format; straight file drops use CF_HDROP and a list of filenames instead of the descriptor/contents pairing. OK, fair enough. What took me longer to figure out was why QueryGetData() was "succeeding": it was actually returning S_FALSE instead of an error code for unsupported formats. This makes sense, except that it's not documented behavior. I have a habit of using the SUCCEEDED() macro for HRESULT values instead of comparing against S_OK under the belief that that is the more correct behavior, but after getting burnt multiple times I'm beginning to wonder if the other way is safer.

The second and uglier case was the virtual-to-virtual case, specifically dragging from a .zip file. In this case there is no direct file on disk, so the shell extension handling .zip files passes the data through a channel instead. The CFSTR_FILEDESCRIPTOR format tells you the metadata for the files, and the CFSTR_FILECONTENTS format is used to extract the actual files. However, the docs don't mention anywhere that there are both narrow and wide versions of the former (CFSTR_FILEDESCRIPTORA/CFSTR_FILEDESCRIPTORW) and the OS apparently does not support both or convert between them automatically. This means that if you just use CFSTR_FILEDESCRIPTOR as recommended you will actually get different behavior depending on whether you compile as Unicode or MBCS. On Windows 7 x64, I'm only seeing the request for the wide version succeeding, and although I can't test it, I suspect that with some other programs or possibly on Windows 9x I would only see the narrow format available. The best conclusion I can draw from this is that the procedure in the Platform SDK docs for handling this format in a drop target is fatally incomplete and you actually have to support both formats. What a mess!

Anyone dealt with implementing drag-and-drop file targets before? I'd love to hear if what I've said above is correct.

Comments

This blog was originally open for comments when this entry was first posted, but was later closed and then removed due to spam and after a migration away from the original blog software. Unfortunately, it would have been a lot of work to reformat the comments to republish them. The author thanks everyone who posted comments and added to the discussion.