Page 4 of 7

Re: Drag&Drop from Outlook (Express) - Possible?

Posted: Tue Feb 18, 2014 10:41 pm
by Thunder93
Just in regards to Outlook Express.. PureBasic DragDrop Lib doesn't work / support Outlook Express attachment drop methods.

srod's OLE drop handling - http://forum.purebasic.com/english/view ... b0#p436579

Worked, but it was stealing my mail attachments. :)

RASHAD's DragQueryFile_ & #WM_DROPFILES - http://forum.purebasic.com/english/view ... b0#p436494

This also worked (tested w/ Images and .Doc files). Both sources weren't altered.

Re: Drag&Drop from Outlook (Express) - Possible?

Posted: Tue Feb 18, 2014 10:54 pm
by Thunder93
Little research I done.. I do know that Outlook Express attachment drops is w/ CF_HDROP. This suppose to be predefined, and no need for RegisterClipboardFormat. However, I might be overlooking, or misunderstanding something. PB only works off of RegisterClipboardFormat_ usage.

Re: Drag&Drop from Outlook (Express) - Possible?

Posted: Wed Feb 19, 2014 5:32 pm
by mesozorn
Well, I've been working at this for several days with no luck whatsoever. I've experimented with modifying srod's code and testing at the DragEnter procedure to see whether it will correctly recognize the format of the data being sent via the clipboard, as such:

Code: Select all

Procedure.i DropTarget_DragEnter(*this._IDropTarget, dataObject.IDataobject, grfKeyState, pt.q, *pdwEffect.LONG)
  Protected result=#S_OK, thisFormatEtc.FORMATETC
  cf_descrip=RegisterClipboardFormat_(#CFSTR_FILEDESCRIPTOR)
  *this\blnAllowDrop = #False
  If *pdwEffect = 0
    result = #E_INVALIDARG
  Else
     With thisFormatEtc
       \cfFormat = cf_descrip
       \ptd =#Null
       \dwAspect = #DVASPECT_CONTENT
       \lindex = -1
       \tymed = #TYMED_ISTORAGE
     EndWith
      check=dataObject\QueryGetData(thisFormatEtc)
      If check = #S_OK
        *this\blnAllowDrop = #True
        DropTarget_SetEffects(grfKeyState, *pdwEffect)
        Debug "okay"
      Else
        Debug check
        *pdwEffect\l = #DROPEFFECT_NONE
      EndIf
      
  EndIf
  ProcedureReturn result
EndProcedure
I have tried every single possible combination of settings for the cfFormat and TYMED members of the FORMATETC structure (istorage, istream, hglobal etc) and no matter what, the call to the QueryGetData method of the iDataobject always returns the exact same error message: "Invalid value for pformatetc" as described here:
http://msdn.microsoft.com/en-us/library ... 85%29.aspx

Dragging an Outlook attachment over the window and calling this method produces the same result, all the time, regardless of the settings for thisFormatEtc. I have looked over the VB code provided as well as a couple of other examples, and they all seem to be using filedescriptor in conjunction with either hglobal or istorage, and yet in the PB test code it fails every time. What's strange is that instead of reporting a member-specific error like incorrect cfFormat or incorrect tymed value, it just very generically claims that the entire formatetc structure is invalid, which of course it isn't.

I will keep trying and researching but at this point I am starting to lose hope that it is possible at all to handle Outlook attachments from within PB. Maybe I am just missing some obvious prerequisite step, but everything at MSDN and in this thread seems to indicate that QueryGetData should work with these parameters. Yet it doesn't.

Re: Drag&Drop from Outlook (Express) - Possible?

Posted: Wed Feb 19, 2014 5:43 pm
by Thunder93
In regards to Outlook Express. I figured it out with just the PB DragDrop Lib. :mrgreen:

Will poster more after I do some further experiments.

Re: Drag&Drop from Outlook (Express) - Possible?

Posted: Wed Feb 19, 2014 5:55 pm
by mesozorn
Thunder93 wrote:In regards to Outlook Express. I figured it out with just the PB DragDrop Lib. :mrgreen:
Will poster more after I do some further experiments.
Outlook Express is considerably easier to work with in regard to handling drag-drop operations of email attachments. Outlook proper however, bears absolutely no similarity whatsoever to Express in its behaviour toward this type of data transfer.

Re: Drag&Drop from Outlook (Express) - Possible?

Posted: Wed Feb 19, 2014 6:02 pm
by Thunder93
Maybe easy.. But I've not seen any posted code using just the PB DragDrop lib and work for Outlook Express.

Re: Drag&Drop from Outlook (Express) - Possible?

Posted: Wed Feb 19, 2014 7:17 pm
by mesozorn
Thunder93 wrote:Maybe easy.. But I've not seen any posted code using just the PB DragDrop lib and work for Outlook Express.
Not trying to diminish your accomplishment... just meant Express cooperates more in general around these sorts of issues than Outlook does.

Having done some further research, I believe the problem lies in the fact that the recipient drop-target window still has to be registered to accept that specific type of data object (email attachments), in much the same way that is normally done natively within PB via:

Code: Select all

cf_descrip = RegisterClipboardFormat_(#CFSTR_FILEDESCRIPTOR)
EnableWindowDrop(0,cf_descrip,#PB_Drag_Copy)
This code above enables the window to receive attachment-type objects, however also invokes PB's native Drop-Lib to handle all such events. Using srod's code instead to create a custom handler, this step is skipped and the window is never told/registered to handle this obscure non-standard drop-data type. Thus it tries to handle the drag-over, but cannot do so successfully when trying to call QueryGetData, because the window does not "like" the type of data contained therein.

Unfortunately I know of no way to combine these two things, so that the window gets registered to accept Filedescriptor drops, but then also redirected to a custom handler for the actual processing. The regular WinAPI call:

RegisterDragDrop_(WindowID(#Window), *this)

..apparently only registers the window to accept regular, standard drops from the filesystem/explorer exclusively, and nothing else. Those elsewhere on the net who've succeeded in implementing accepts-from-outlook have had to write their own custom DLL file in C++ in order to accomplish this. And that is definitely beyond the scope of my current project/familiarity.

I could be wrong about my hypothesis of course, but that is my best guess based on research done. And as a result of this conclusion, I am giving up on this endeavour altogether. Thanks to everyone who tried to help nonetheless.

EDIT: And, just after typing that and trying one last desperate thing, I made a little bit of progress at last. So it is not quite abandoned just yet...

Re: Drag&Drop from Outlook (Express) - Possible?

Posted: Wed Feb 19, 2014 8:56 pm
by srod
That code I gave should be able to handle drops of any registered clipboard format (in principle at least). You need to set the cfFormat fields in the various methods where appropriate. Of course getting ahold of the data is another matter... memory streams and the like. You will have to rip out the cf_hdrop stuff.

When you use RegisterDragDrop_() you must pass a COM object pointer which you set-up (as my code does). No need to use a dll for that.

Re: Drag&Drop from Outlook (Express) - Possible?

Posted: Wed Feb 19, 2014 10:22 pm
by mesozorn
srod wrote:That code I gave should be able to handle drops of any registered clipboard format (in principle at least). You need to set the cfFormat fields in the various methods where appropriate. Of course getting ahold of the data is another matter... memory streams and the like. You will have to rip out the cf_hdrop stuff.
When you use RegisterDragDrop_() you must pass a COM object pointer which you set-up (as my code does). No need to use a dll for that.
Thanks, I am making progress and have the Drag_Enter procedure successfully identifying and QueryGetData'ing Outlook attachments using the appropriate cfFormat and Tymed members. The strange thing at the moment is that although that DragEnter method works fine, when I actually release the mouse button holding one of those attachments, the DropTarget_Drop() procedure is simply never called at all. I have a debug line right at the very top and it just isn't being triggered in any way.

If I drop a regular filesystem file then it works perfectly and triggers the debug line. But using an Outlook attachment, it doesn't even get to the point of testing iDataObject GetData() since the procedure just doesn't run. I'm sure there's some reasonable explanation for this and I'll figure it out, but so far it's a mystery. All of the other variables like:

Code: Select all

*this\blnAllowDrop = #True
DropTarget_SetEffects(grfKeyState, *pdwEffect)
...are being set identically to when a CF_HDROP is detected and occurs, so I'm not sure why the DropTarget_Drop() procedure simply isn't activating right now. I'm obviously fumbling around in the dark with this COM stuff so just the natural learning curve I suppose. One of those interface parameters must not be getting set right, but no clue which one...

Re: Drag&Drop from Outlook (Express) - Possible?

Posted: Wed Feb 19, 2014 10:37 pm
by srod
Is the cursor the usual drag one as you hover over the window?

The most likely reason is that one of the methods or helper functions is setting the effects to #DROPEFFECT_NONE. Check if the DropTarget_DragOver() method is being called (chuck in a debug). If it is, debug the value of *pdwEffect\l just before the method exits. Check this value is not #DROPEFFECT_NONE.

Re: Drag&Drop from Outlook (Express) - Possible?

Posted: Wed Feb 19, 2014 10:45 pm
by mesozorn
srod wrote:Is the cursor the usual drag one as you hover over the window?
The most likely reason is that one of the methods or helper functions is setting the effects to #DROPEFFECT_NONE. Check if the DropTarget_DragOver() method is being called (chuck in a debug). If it is, debug the value of *pdwEffect\l just before the method exits. Check this value is not #DROPEFFECT_NONE.
Even in your original unedited example, the mouse cursor never changes and shows the "None allowed" circle all the time, even though the drop operation is permitted when attempted. In my edited version it still never changes, although drops of filesystem files work correctly, and Outlook attachments don't.

I added some more debug lines and found then when I release the mouse button it is calling the DropTarget_Leave method, just as when I move the mouse outside the window. Instead of the Drop method. When dropping a proper file it works as expected. DragOver is called correctly in all cases and debugs continuously as I hover over the window. It's just Drop that isn't getting called...

EDIT: Yeah, *pdwEffect\l is zero when DragOver with an Outlook attachment, and 2 when using a filesystem file. Have to find where that's occurring...

FURTHER EDIT: I'm never ever changing the value of *pdwEffect\l manually. It comes in as an argument to the DragEnter method and then gets set subsequently by your DropTarget_SetEffects() procedure, and I have that happening identically in both cases (file and attachment) so I don't know why the result is different. Maybe I have to just force it to a specified value myself when a FileDescriptor format is detected..?

Re: Drag&Drop from Outlook (Express) - Possible?

Posted: Wed Feb 19, 2014 11:00 pm
by srod
Something doesn't add up there. If the cursor shows the forbidden symbol then the drop shouldn't fire.

Re: Drag&Drop from Outlook (Express) - Possible?

Posted: Wed Feb 19, 2014 11:02 pm
by mesozorn
Okay, I am getting closer... with Filesystem files the default "Effect" sent to the interface is DROPTARGET_MOVE. So you can drag and drop using only the mouse, no problem. When dragging Outlook attachments it prefers to use DROPTARGET_COPY, which means the SetEffects and Drop methods are forcing the user to hold the CTRL key down in order to get a cooperative response. As soon as I tried that, the mouse cursor changed and I was able to drop the attachment and trigger the Drop() method.

I'll have to fiddle with the code a bit to allow DROPTARGET_COPY to be used more easily without requiring the Control key to be pressed as well.

Re: Drag&Drop from Outlook (Express) - Possible?

Posted: Wed Feb 19, 2014 11:10 pm
by srod
Right that is just the way I set the code up. You can easily change that by altering the DropTarget_SetEffects() function. This is not part of the COM object, just a helper function I created to help out.

The way I set it up is that if the user 'currently' has the control key pushed down, then we check if the original drag operation allowed a copy (which depends on Outlook itself). If so, I allow things to proceed. If the control key is not down at any given time, then the helper function checks to see if the drag source allows a move operation. If so, we allow things to proceed. In all other cases, the helper function marks the drop as invalid if the user were to release the key at that instant (with the #DROPEFFECT_NONE value).

You can change any of this behaviour.

The simplest way is to use something like :

Code: Select all

Procedure DropTarget_SetEffects(grfKeyState, *pdwEffect.LONG)
  If grfKeyState&#MK_CONTROL
    *pdwEffect\l = #DROPEFFECT_COPY
  Else
    *pdwEffect\l = #DROPEFFECT_MOVE
  EndIf
EndProcedure

Re: Drag&Drop from Outlook (Express) - Possible?

Posted: Wed Feb 19, 2014 11:26 pm
by mesozorn
srod wrote:

Code: Select all

Procedure DropTarget_SetEffects(grfKeyState, *pdwEffect.LONG)
  If grfKeyState&#MK_CONTROL
    *pdwEffect\l = #DROPEFFECT_COPY
  Else
    *pdwEffect\l = #DROPEFFECT_MOVE
  EndIf
EndProcedure
Just tested this, and an odd quirk with Outlook seems to be that it sends the dragsource in a way that will ONLY allow it to be received by the Drop() method if the Effect is set to COPY, rather than move. So with the code above, setting the effect to MOVE if the control key isn't pressed, still causes the window to reject the drop and trigger the Leave() method instead. If I force it to COPY instead, the Drop works perfectly fine.

Tailoring that helper function shouldn't be too challenging at this point, and in fact I may just leave the Effect unaltered unless it is a null/invalid one. At least this making a bit more sense now...