I solved this problem, but discovered another one. The flavor sent by the flex panel has been changed, so that it's a text flavor instead of an URL flavor. My method couldAcceptType works now :
AutocatDNDCustomFlavorHelper::CouldAcceptTypes(const IDragDropTarget* target, DataObjectIterator* dataIter, const IDragDropSource* fromSource, const IDragDropController* controller) const
if (0 != dataIter && 0 != target)
// Check for URL Flavor in the drag
DataExchangeResponse response = dataIter->FlavorExistsWithPriorityInAllObjects(kTEXTExternalFlavor);
return DragDrop::TargetResponse(response, DragDrop::kDropWillCopy);
The problem is now in the ProcessDragDropCommand method. Here is the code :
ErrorCode AutocatDNDCustomFlavorHelper::ProcessDragDropCommand(IDragDropTarget* target, IDragDropController* controller, DragDrop::eCommandType action)
// retrieve drop data
IPMDataObject* dragDataObject = controller->GetDragItem(1);
uint32 dataSize = dragDataObject->GetSizeOfFlavorData(kTEXTExternalFlavor) ;
The problem is the IMPDataObject I get is nil. There is no item in the controller. However, there were items in the CouldAcceptTypes method, in the DataObjectIterator. So, where are my items ?
I tried using a custom CDataExchangeHandlerFor, but could not really understand what its usage was for. It didn't work anyway.
Has anyone an idea ?
There are two reasons for which I use GetDragItem(1) :
- It works on Windows
- The documentation in the header says it should be so :
// ---------- Content of the doc
/** Retrieve a particular drag item from the current drag
@param itemID IN the id of the item to retriver (almost always 1).
@precondition a drag must be in progress
@return a pointer the drag item
// ---------- Content of the doc
I tried to iterate as you say, but without any success. Is there a chance that InDesign consumes the content of my drag with one of its helpers, before mine is called ? The Flavor I use is not custom, so I thought it could be possible. The iterator on dragged objects in CouldAcceptTypes method is not empty, so my helper accepts the drop. But when it is performed (ProcessDragDropCommand method), I try to get the items from the controller, and they are absent. The GetItemCount returns -1 though.
Would you have any other idea ?
My use of GetDragItem is only in experimental code of a development plugin and I did not verify that for your case.
I have a production plugin though that accepts browser drag&drop of links. My approach was to substitute the links during Internalize with some download to be placed by the standard file dropping place helper, thus I did not use GetDragItem at all. Internalize already receives the IPMDataObject ...
Browsers deliver many flavors at the same time, different even by the kind of object the link is bound to. In that plugin I had to do severe shuffling (ReorderFlavors during multiple helpers) to get the whole thing to work - I think kSysFileDataExchHandlerNetscapeHelperBoss was stealing away anythink resembling a link at highest priority.
The original debug session was 5 years ago with InDesign 2 so I don't remember the nifty details, and just pray that nothing breaks when I have to do another port or support another browser. From that experience I remember the whole InDesign D&D mechanism is an overcomplicated mess of too many phases, but still insufficiently factored in the later phases.
I finally found a "solution". This one is dirty, but I could not find any other clean solution, so I use it.
The solution is the following one : In the couldAcceptTypes method, I get the first object of the DataObjectIterator, and store the itemID I retrieve from the object contained within. I store it with a dirty memcpy (No other solution, the method is declared as const).
Then, in the ProcessDragCommand, I retrieve the itemID, and then call GetDragItem with this itemID. There I finally get the item.
Why should I do such a solution ? Because the itemID on PC is alsways 1. But on Mac, the one I retrieved was something like 719531, or whatever. I don't know why.
If this solution can help someone, this will be good. If someone find a clean solution, I would appreciate to know it.
@Dirk : I tried your solution, but could not manage it to make it work. I may have done something wrongly, I don't know...
In your CouldAcceptTypes function, you get access to the IPMDataObject via dataIter->First() Here you can read out the content as either kTEXTExternalFlavor or kUNICODETEXTExternalFlavor, depending on what you like the best. At this point you can also check if it actually something that is your, if you prefix from Flex or is looking for a specific string format. Store the result in a static variable and you can use this once you get called in ProcessDragDropCommand.
I tried to use the flavors you mentioned, before I knew the problem with the itemID, without success at that time.
The fact is I used a static variable, but I had problem with the fact the CouldAcceptTypes method is declared as const. That's why I use the very dirty solution of the memcpy.