【问题标题】:DoDragDrop() from another thread来自另一个线程的 DoDragDrop()
【发布时间】:2010-08-21 16:40:31
【问题描述】:

每次我想让用户拖动控件时,我都会调用该控件的 DoDragDrop。

拖放工作正常,但我对周围的事情有疑问:

  1. DoDragDrop 完全阻止表单,没有计时器事件跳转,没有处理任何绘制消息。

  2. DoDragDrop 不仅会阻止拖放操作,还会阻止目标程序完成放置事件(即 explorer.exe 的吸吮代码)。依赖其他程序的代码很烂。

我想从一个新线程调用 DoDragDrop。

试过这个:

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

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

但它似乎不起作用。我的意思是:当像这样从其他线程执行 DoDragDrop 时,我的程序或其他程序中的其他控件不会接收拖放消息。

还有其他解决方案吗?

【问题讨论】:

  • 要不要提供更多关于失败的信息而不是“它似乎不起作用”?
  • 当像这样从其他线程执行 DoDragDrop 时,我的程序或其他程序中的其他控件不接收拖放消息。

标签: c# winforms multithreading drag-and-drop blocking


【解决方案1】:

DoDragDrop 方法停止处理事件,直到第一个鼠标事件(例如鼠标移动)。所以我找到的解决方法很简单——你只需要在调用 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】:

    您需要忘记使用线程,它只会将 D+D 通知传递到在该线程上创建的窗口。哪个不是您的控件。

    对于“代码很烂”的诊断,我无能为力。 DoDragDrop() 调用本身确实会阻塞,直到释放鼠标按钮。 COM 代码内部的另一个消息循环将接管并传递 Windows 消息。计时器和绘画消息应正常传递。除非您发布一些重现代码,否则很难进行诊断。

    【讨论】:

    • 我怀疑他所说的可能是资源管理器在放置后进入复制操作并导致他的应用程序 UI 在执行复制时阻塞。我知道它对 WinRAR 是这样的......
    • 有一个 D+D 协议允许应用程序以后期绑定方式传递数据。这在 .NET 程序中很难实现,当然不是“数据”。
    【解决方案3】:

    您可能希望DoDragDrop 退出并异步完成工作。

    Here is the answer.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多