DoDragDrop() from another thread

2019-03-03 17:00发布

问题:

Every time i want let the user to drag an control, i calling DoDragDrop of that control.

The drag & drop works fine, but i have problem with things around:

  1. DoDragDrop completely blocking the form, no timer events jumps, no paint messages handled.

  2. DoDragDrop blocking not only for the drag & drop operation, but until target program finishing with the drop event (I.E. explorer.exe's suck code). Depending on other program's code is sucks.

I thought to call DoDragDrop from a new thread.

tried this:

Thread dragThread = new Thread(() =>
{
    Form frm = new Form();
    frm.DoDragDrop("data", DragDropEffects.All);
});

dragThread.SetApartmentState(ApartmentState.STA);
dragThread.IsBackground = true;
dragThread.Start();

but it doesn't seems to work. I mean: when doing DoDragDrop from other thread like this, other controls within my program or other programs does not receiving drag&drop messages.

Any other solutions?

回答1:

The DoDragDrop method stops processing of events until first mouse event (for example mouse move). So the workaround I found is very simple - you just need to simulate mouse event with the same mouse position just before calling DoDragDrop:


void XYZControl_MouseDown(object sender, MouseEventArgs e)
{
    var senderControl = (Control) sender;
    ...
    Cursor.Position = senderControl.PointToScreen(new Point(e.X, e.Y));   // Workaround!
    if (DoDragDrop(senderControl, DragDropEffects.Move) == DragDropEffects.Move)
    {
    ...
    }
....
}


回答2:

You need to forget about using a thread, that's only going to deliver D+D notifications to the windows that were created on that thread. Which will not be your controls.

I can't do much with a "code is sucks" diagnostic. The DoDragDrop() call itself will indeed block until the mouse button is released. Another message loop, internal to COM code will take over and deliver the Windows messages. Timer and paint messages should be delivered as normal. A diagnostic is very hard to come by until you post some repro code.



回答3:

You probably want the DoDragDrop to quit and do the job asynchronously.

Here is the answer.