Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

OLE drag and drop

Status
Not open for further replies.

Nigel Gomm

Programmer
Jan 10, 2001
423
CA

what would stop me seeing an OLESetData event being fired on the source object when the destination object issues a odataobject.getdata() ?

Instead the destination object's odataobject.getdata(1) simply returns false.

(it all works when i .setdata() within the OLEStartDRag event but I'm hoping to avoid that because i want the option of requesting different formats depending on the different possible destination objects.)


n


 
You're right, the help topic of OLESetData describes:

help said:
The OLESetData event occurs when the GetData method is executed. Within the OLESetData event you can place data in the DataObject in the specified format with the SetData method. This technique is called "delay rendering" and allows you to put data on the DataObject only when it is requested.

So in general, your idea of setting data late when you know from the target what data type is necessary, is supported.

A remark in the GetData method help topic says:
help said:
The value returned by the GetData method is determined by the format of the data specified with nFormat or cFormat. False (.F.) is returned if the DataObject doesn't contain data in the format you specify with nFormat or cFormat.

I don't know what would lead to the situation you describe, the full code would help to analyze the problem. Before we get there, can you coverage profile what happens? The only reasonable way you get an immediate .f. is setData already only set another than Format 1 (CF_TEXT). Maybe because you have set something to automatic behavior, which is not helpful when you want to make use of all the special features and get most out of Ele Drag&Drop features. What does not fit in here is that I think Automatic Drag&Drop would always put in text data, but that may depend on the source object, too, this may only be true for VFP source objects, perhaps?

With coverage profiling I'd hope to see when and how OleSetData already was triggered and what was put in as data format.

ASide of all of this, the obvious hack to live with the situation and just accept it would be setting text format data in the form of XML, for example, that the target can either extract the text of or could be turned into other formats, so live without the nice feature of a late callback to OLESetData and instead put in something that's of universally usable data value.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Olaf,

the XML idea won't work because i won't always be dropping into my application; one of the formats i want to set is a filelist (15) to drag a file into, for instance, an outlook email message.

But when i drop into one particular form/control in my application it would be useful to have more/different information.

I have tracked the events with coverage and have diagnostic code in all the OLExxxx events. The OLESetData event just isn't being fired.

For the moment i have it working by setting format 15 in the OLEStartDRag... and then doing some lookup within that one other form/control to get the extra information i need. But that code is expensive and introduces a delay.

It's early sat morning now and i haven't had my coffee yet..... i'll see if i can extract the relevant code and settings into something understandable here over the weekend.

n

 
so... dragging from class propertyimage to pgphotos2

[pre]DEFINE CLASS pgphotos2 AS ctl32_scontainer


OLEDragMode = 0
OLEDropMode = 1



PROCEDURE OLEDragOver
LPARAMETERS oDataObject, nEffect, nButton, nShift, nXCoord, nYCoord, nState
nEffect = 1
this.OLEDropHasData = 1
nodefault
ENDPROC


PROCEDURE OLEDragDrop
LPARAMETERS oDataObject, nEffect, nButton, nShift, nXCoord, nYCoord
LOCAL ARRAY laPK(1),lafiles(1)

=diagnostic(oDataObject.GETDATA(1))
= oDataObject.GETDATA(15,@lafiles)

NODEFAULT
ENDPROC


ENDDEFINE
*
DEFINE CLASS propertyimage AS myimage


OLEDragMode = 0
OLEDropMode = 2
Height = 136
MousePointer = 15
Width = 150
index = 0
order = 0
filename = .F.


PROCEDURE OLEStartDrag
LPARAMETERS oDataObject, nEffect
nEffect = 2
oDataObject.SETDATA(FULLPATH(THIS.filename),15)
ENDPROC


PROCEDURE MouseMove
LPARAMETERS nButton, nShift, nXCoord, nYCoord
this.OLEDrag(.t.)
ENDPROC


PROCEDURE OLESetData
LPARAMETERS oDataObject, eFormat
=diagnostic(eFormat)
DO CASE
CASE TYPE('eformat') != 'N'
CASE eFormat = 15
oDataObject.SETDATA(FULLPATH(THIS.filename),15)
CASE eFormat = 1
oDataObject.SETDATA(TRANSFORM(THIS.INDEX)+";"+TRANSFORM(THISFORM.currentrecord.propref)+";"+FULLPATH(THIS.filename),1)
ENDCASE
ENDPROC


ENDDEFINE
[/pre]


several propertyimage objects will be added to the container. Most of the time users are dragging and dropping within the parent container to re-order the photos... which is why i need extra info about current position etc. Sometimes they drag to a different instance of the same form for another property (property in the real estate sense) and sometimes they want to drag to an entirely different application. Setting format to 15 in the startdrag event is at least working (and i've now put the extra info onto a property on the application object for the desitination object to pick up).
i'm just curious to know why the OLESetData isn't firing.
Capture_kdzblr.jpg
 
OK, so you got it working.

Fist of all, why would the target need the info about the source position, the source has a completion event and can handle itself, ie remove itself, the target only needs to know which image it should be at which new/current position.

Besides that, I also don't know why no OleSetData event happens. I can reproduce that and the Hackers guide tells it always happens, whenever you have code there. The docs say it's only triggered if a data format as the target requests is not present. When you ClearData() at OleStartDarg that should be the case so no matter if the help or the Hackers Guide is correct you should get the OleSetData event, yet it doesn't happen.

I fear it depends very much what format the target requests and when that's not in your hand like in the case of dropping into a Windows Explorer window, I fear most of the time it will be 1 = CF_TEXT and even a cleared data object would answer that with an empty string rather than triggering the OleSetData event.

The solutions sample also does not help much.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Olaf,

sorry... you can reproduce the OLESetdata event NOT happening?

Wonder if it's a VFP9<->Windows10 thing?

I can live with it as it is but just wanted to be sure i hadn't misunderstood in case i ever need to drag something more exotic.....

n
 
Yes, that. I didn't program a drag target, let me complete that, but when you drag to Windows desktop or Windows Explorer that should also work. I see OleGiveFeedback events, also from other Processes.

Bye, Olaf.

Olaf Doschke Software Engineering
 
OK, I think I found what helps: When you set all possible formats in the oDataObject5 OLEStartDrag of the source:

Code:
*Source object OleStartDrag:
LPARAMETERS oDataObject, nEffect

oDataObject.ClearData()
For nformat = 1 to 15
    oDataObject.SetFormat(nformat)
EndFor

I still don't get the mouse icon to allow drop everywhere, so I guess there are more formats. Also, not every pixel everywhere expects OLE data to drop. But in some places, like the Search Box of Google in a browser, I do get OLESetDAta events, which ask for Format 13 (Unicode text). The browser triggers two events (maybe second try because I don't SetData). And both events happen before the actual drop.

So this could also be problematic if you get such events before the actual drop event and move over several possible targets, that would trigger you to set a specific format type and then OleSetData would perhaps not reoccur.

Anyway, in short, you could try the loop in OleStartDrag of the source object which I think means the OLE source offers to have any format without setting the data om that format already. And then any possible target, which looks out for certain formats, finds out the OLE source offers that.

Bye, Olaf.

Olaf Doschke Software Engineering
 
hmmm... i had tried setting both formats 1 and 15 in the startdrag before but the second call appeared to be replacing the first rather than being additive.....

i'll give it another go when i get the chance...


n
 
Well, well, only halfways working. I earlier had reduced the loop to go from 13 to 13 and that only set format 13. NOw that I have the loop from 1 to 15 I don't get format 13 requests, but I do get requests for 1 and 15 from different drop targets. I reversed the order from 15 to 1 first, and still got other than 1 requests, but as it is now, it's neither just the last setting nor fully cumulative.

Edit 1:
No, it still works for me, I forgot the request of Format 13 comes from things like Google search box, where Unicode text is wanted. I still get requests for 1 from many targets in VFP itself, 13 for boxes like Google search and 15 from Windows Explorer pointing to folders, for example. Without the loop no requests are triggered, no OleSetData event occurs. So setting all formats helps, still a problem is that these requests come in before the OleDrop event, just at any DragOver, it seems.

Edit 2:
It becomes clear, why this is the behavior about event triggering, in OleDragOver you're asked to request the format you want from the oDataObject and there you make a call of GetData with the format, that causes the OleSetData event in the source object. And as it is that way, I see no reason to wait for these events, then you can also set several formats at OLEDragStart and the drop target will pick out what it wants. The OleSetData only happens once per format, when you set the requested format. Next requests of the same format are then already fulfilled by the set value.

One reason to wait with filling in all data is, when one of the formats would transport something binary and large that may never be requested. But even 15 is just a list of file names, not the files or their content itself.
One other reason is, you want to be recent, you want to transfer the latest data about something. The mechanism doesn't really support this, though, as the first request of a target is when you put in data, when you don't drop there, you never get the same format request again, all targets requiring the same format later get what you put in initially. Of course the next drag/drop operation starts fresh, but within one drag you'd only get multiple requests of the same format, if you clear the dataobject. But at what time would that be applicable? In each OleGiveFeedback event?

And another thing, which now bugs me: When I drop into the Google search box that works, but then it seems the oDataObject becomes a zombie object, a dangling reference. The form does not close. Neither the debugger nor VFPs Program menu shows anything on the call stack, any running code, but the form only releases with CLEAR ALL.

So there is something about OLE drag&drop VFP has not caught up with, I guess. But I haven't used this in my projects I always could do either without drag&drop or with native VFP drag&drop, so I don't know whether some or all these quirks are new or known or even by design. Surely a dangling object reference should not occur. And just while I'm at discussing OLe drop to Google search box, you have to use STRCONV(ansitext,5) and convert to Unicode, not UTF-8, though browser encode text with UTF-8, this has nothing to do with the html encoding. What you also have to do is add a CHR(0) before Unicode conversion, otherwise Google writes one gibberish character after the text. It's not that exceeding to read past the end of the dropped Unicode text, what hinders the VFP form to close. Adding the CHR(0) the text is transferred correctly, but the VFP form still refuses to close after a drag&drop has occurred and is completed. OleCompleteDrag occurs and informs the source object Google did a COPY (nEffect=1), that's okay and should end the drag, the oDataObject should also be released, but you have no hands on that, the OleCompleteDrag only allows you to override the effect or cancel the drop, but you don't get the oDataObject reference to call ClearData() on it to enable easier release, if that would help. Anyway, it's also not clear whether to blame Google or the Browser. The OLE operation is done to the browser process, of course.

OK, last thing: I tested several browsers. Chrome lets the form hang, FireFox drops the text twice but the VFP form can release cleanly. In MS Edge the drop does not work always and the VFP form hangs again. Internet Explorer is unproblematic again. So in part this also depends on what other application you drag to.

Bye, Olaf.

Olaf Doschke Software Engineering
 
oh you're having way too much fun !

yes, the secret seems to be the .setformat in OLEStartDRag.

[pre]LPARAMETERS oDataObject, nEffect
nEffect = 2
oDataObject.CLEARDATA()
odataobject.setformat(1)
odataobject.setformat(15)
[/pre]

causes the .getformat() and .getdata() in OLEDragDrop to work as documented.
i.e.
odataobject.getformat(1) now returns true
and odataobject.getdata(1) causes the .OLESetdata() in the source object to fire. Likewise .getformat(15) also returns true and .getdata(15) returns the filelist.

So that answers my original question .....


however, that doesn't help when dragging to MS Outlook. It checks for both formats 1 and 15 (i.e. .olesetdata() fires with parameter eformat set to 1 and then again set to 15) but outlook prefers the text format and proceeds with that.... so i end up dragging a filename+mydata text into an email body rather than the filelist which creates an attachment. And perhaps that behaviour was why i didn;t think the .setdata() was additive?

Dragging to outlook is the main reason i'm looking at this again now... so i'll have to go back to .setdata( ,15) in OLEStartDrag().

n


Update : now i re-read the VFP help it does indeed tell us this in the remarks section for the setformat method <sigh>.
 
Yes, the remark in the SetFormat. I read that later after I tried adding multiple formats. SetData itself also is cumulative, ie SetData in format 1 after setting format 15 does not clear that, the dataobject is more complex than _cliptext.

You can't tell Outlook to prefer format 15, so the only way to force it is only providing format 15.

The problem also is, that the getdata calls come from DragOver, Format 1 is often asked, so even dragging over other things like a notepad would ask for format 1 data and then Outlook will use that, too.
I also tried dragging to the attachment line instead of the mail body, even then format1 is preferred, though the attachments line doesn't do anything with it.

And if you only offer format 15 that doesn't cover other cases. Anyway you do it, that does not work out.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top