how to do drag and drop asynchronously?

G

Guest

Hi, all.
I want my program act as an drag source and do drag and drop asynchronously.
So, I created a class CDataObject which implements interfaces IDataObject and IAsyncOperation.
To begin drag and drop, I wrote the following code:
CDataObject* pDataObj = new CDataObject(...);
if (pDataObj)
{
OleFlushClipboard();
HRESULT hr = pDataObj->QueryInterface(IID_IDataObject,(LPVOID*)&m_pMyDataObj);
pDataObj->Release();
if (SUCCEEDED(hr) && m_pMyDataObj){
HRESULT hr = pDataObj->QueryInterface(IID_IAsyncOperation,(LPVOID*)&m_pAsyncOp);
if(SUCCEEDED(hr)){
m_pAsyncOp->SetAsyncMode(VARIANT_TRUE);
IDropSource *pDropSrc = (IDropSource *) new CDropSource;
DWORD dwEffect = 0;
DoDragDrop(m_pMyDataObj,
pDropSrc,
DROPEFFECT_COPY | DROPEFFECT_MOVE,
&dwEffect);
m_pMyDataObj->Release();
pDropSrc->Release();
...
}
}
}

According to MSDN, if AsyncMode is set to VARIANT_TRUE, The drop target (In my program, the only possible target
is Windows explorer) will do drag and drop asynchronously.
Yet, although I set this flag, windows always do drag and drop in the same thread as the UI of my program.
What's wrong with my code? Can any one help me?
Thank you very much!

p.s. I can not understand this line in MSDN, section IAsyncOperation::SetAsyncMode, is this the key problem?

If fDoOpAsync is set to VARIANT_TRUE, SetAsyncMode must call IAsyncOperation::AddRef,
and store the interface pointer for use by IAsyncOperation::EndOperation.
 
B

Bart Jacobs

Wei Junping,
According to MSDN, if AsyncMode is set to VARIANT_TRUE, The drop target (In my program, the only possible target
is Windows explorer) will do drag and drop asynchronously.

I think MSDN says something else. MSDN says that if AsyncMode is set to
VARIANT_TRUE, then the drop target has the *option* of performing data
transfer asychronously. The drop target is not *required* to perform
data transfer asynchronously.
Yet, although I set this flag, windows always do drag and drop in the same thread as the UI of my program.
What's wrong with my code?

I think there is nothing wrong with your code. "Asynchronous" does not
necessarily mean: "in another thread". It just means that DoDragDrop
does not wait for the data transfer to finish before returning. In any
case, DoDragDrop does not return before the mouse button is released.
p.s. I can not understand this line in MSDN, section IAsyncOperation::SetAsyncMode, is this the key problem?

If fDoOpAsync is set to VARIANT_TRUE, SetAsyncMode must call IAsyncOperation::AddRef,
and store the interface pointer for use by IAsyncOperation::EndOperation.

I do not understand this either, but I do not think it is essential.

Greetings

Bart Jacobs
 
B

Bart Jacobs

Wei said:
Thank you very much.
But how can I do drag and drop in a new thread?

What do you mean?

Do you want to call DoDragDrop in a thread that is different from the
thread that receives the mouse button down message? That would not make
sense, I think.

Or do you want to handle incoming IDataObject calls in a different
thread? I don't know how to achieve that. But I think in most scenarios
it is possible to handle each such incoming call in such a short amount
of time that the responsiveness of the user interface is not impaired.

Or something else?
 
G

Guest

I want to handle incoming IDataObject calls in a different thread.
Because In my program, I need to download many files from a remote computer via bluetooth.
Thank you!
 
B

Bart Jacobs

COM delivers calls to an object in the apartment in which the object is
created. If the object is created in a single-threaded apartment (such
as the OLE GUI thread in which you call DoDragDrop), then calls are
dispatched on that thread, which is not what you want for your
CDataObject instance. Therefore, create the CDataObject on another
thread and marshal the interface pointer to the GUI thread, so that you
can pass it to DoDragDrop.

I wonder how well drop targets, such as Windows Explorer, cope with
IDataObject calls that take a very long time. Perhaps a better design
would be to offer a separate command in your application to "download"
the file, and to allow only completely downloaded files to be dragged
and dropped. Note that Internet Explorer also does not allow one to
drag-and-drop a remote file directly, and this does not seem to have
been fatal to its acceptance :)
 
G

Guest

I follow your suggestion
Yet, DoDragDrop doesn't return until the transfer finishes(I do the tranfer in CDataObject::GetData) even if I have set asyncmode to VARINT_TRUE
What's wrong with it
Can you give me some sample code
Thank you very much!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top