How to create responsive drag and drop experience even if lots of processing is required

G

Gunnar

I have a winforms application that can encrypt and unencrypt files. I want
to support drag and drop files out to Windows Explorer.
In my current version I unencrypt my files in the MyListview_ItemDrag Event,
build an array of files and call DoDragDrop() with DataFormats.FileDrop.
This works, but I'm concerned about this architecture. If a user starts to
drag several files from my listView and all of these files are really BIG.
It can take some time to unencrypt these files and place them in a
directory. Meanwhile the application thread is busy and the application
seems unresponsive to the user.

As far as I know, no DragDrop-like Event will trigger in my code when I drop
in an external app like Explorer. So is there no way to postpone the
time-consuming part (unencrypting files) to the DragDrop part when the user
releases the mouse button??

I hope I'm wrong. Any tips, suggestions?
Regards, Gunnar Sundfar
 
A

Andy

If you're using .net 2.0, you can use the BackgrounWorkerProcess
component, and do the actual decryption in the DoWork event handler.
Of course you'll want to NOT respond to drag drop events (since your
process is running on another thread, and you can't tell it to start a
new operation until the previous one is finished).

If you're not using .Net 2.0 (or you want to keep responding to drag
drop events while another file is decrypting), you can spawn another
thread to do the decryption. This will leave your UI thread free to
respond. I really recommend starting with the BackgroundWorkerProcess
component though first, as this is a bit easier to manage than handling
the threads yourself.

HTH
andy
 
G

Gunnar

Yeah, well I don't think I can go down that road because:
If a user is a "fast drag and dropper" where he drag from my app on to
Explorer really fast, the Explorer will present an error message saying that
the files are not there!!!!, while a worker thread is still working with the
time-consuming part.

Gunnar
 
B

Bob Powell [MVP]

If you're using the 2.0 runtime take a look at the BackgroundWorkerThread
for doing your decryption. You can put a placeholder on the drop target
while the files are being decrypted and get an asyncronous notification of
the process progress and notification.



--
Bob Powell [MVP]
Visual C#, System.Drawing

Ramuseco Limited .NET consulting
http://www.ramuseco.com

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.
 
G

Gunnar

Thanks for the feedback. Sure I can utilize the backgroundworkerthread
somehow, but I still don't see the big picture. In my experience, there is
no event triggering in my app when I drop something on an Explorer window.
In the MyListview_ItemDrag Event I can prepare real files or placeholders,
but if there's no events firering when I drop outside my app, then I have no
way of starting a backgroundworker thread and no way of knowing where I
dropped the files, right?

How does Explorer itself do drag and dropping of large files, where you see
the copying-animation??

Confused, Gunnar
 
M

Michael C

Gunnar said:
After some googling, my conclusion is that I guess I need to use the
IAsyncOperation interface described here:
http://msdn.microsoft.com/library/d...cs_programming/transferring/datascenarios.asp
to implement asyncronous drag and drop.

But is this possible in managed code?
Does anyone know of any examples?

Did you get a solution to this? I'm trying to do the same thing where users
can drag images out of my application which are stored in a database. It is
definately possible although possibly quite difficult maybe requiring much
interop. Certainly the idea of using a background thread is not the
solution.

I believe you need to use CFSTR_FILECONTENTS as on this page.
http://msdn.microsoft.com/library/d...basics_programming/transferring/clipboard.asp

This format identifier is used with the CFSTR_FILEDESCRIPTOR format to
transfer data as if it were a file, regardless of how it is actually stored.
The data consists of an STGMEDIUM structure that represents the contents of
one file. The file is normally represented as a stream object, which avoids
having to place the contents of the file in memory. In that case, the tymed
member of the STGMEDIUM structure is set to TYMED_ISTREAM, and the file is
represented by an IStream interface. The file can also be a storage or
global memory object (TYMED_ISTORAGE or TYMED_HGLOBAL). The associated
CFSTR_FILEDESCRIPTOR format contains a FILEDESCRIPTOR structure for each
file that specifies the file's name and attributes.

Michael
 
G

Guest

Michael C is on the right track. The problem is that .Net DataObjects
do not support CFSTR_FILECONTENTS and CFSTR_FILEDESCRIPTOR. The basic
problem is that .Net DataObjects do not support the "lindex" parameter,
which these formats require. The formats allow for multiple streams,
etc. and lindex is what is used to tell DropTargets how many items are
being Drag/Dropped. In other words, you have to roll your own
interfaces using the WinApis. Once you do that, every thing else is at
least possible. See:
http://www.codeproject.com/useritems/FileBrowser.asp
for a very relevant example.
 
G

Guest

Dear Michael C:

Did you find a solution to this? I too am looking for a way to allow DnD
operations between my application and other applications. Trying to find out
how others have gone about this. Performing DnD within a single app is
fairly straight forward and works nicely .... trying to do this between
different apps, though, is proving to be more difficult.

Thanks.
 
M

Michael C

MobileMan said:
Dear Michael C:

Did you find a solution to this? I too am looking for a way to allow DnD
operations between my application and other applications. Trying to find
out
how others have gone about this. Performing DnD within a single app is
fairly straight forward and works nicely .... trying to do this between
different apps, though, is proving to be more difficult.

I still don't have a solution. I was getting into implementing all sorts of
com interfaces to get this working but gave up as it was taking too much
time for a minor feature.

Michael
 

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