允许在窗体的任何位置拖放

本文关键字:任何 位置 拖放 窗体 | 更新日期: 2023-09-27 18:17:31

是否有一种方法可以在一个充满控件的表单中允许拖放?

这个想法是允许用户拖动一个文件在窗体中的任何地方,以便"加载"它。我不需要任何其他的拖放行为,除了这个。

通过将AllowDrop=True仅设置为表单,我得到DragEnter事件,而不是DragDrop事件。

一个想法是使最上面的面板可见的DragEnter和处理DragDrop事件那里,但我想知道如果我错过了一些明显的东西,因为我在这个领域几乎没有经验。

另一个想法是遍历所有控件并订阅与拖动相关的事件。但是我真的不喜欢这种方法。

允许在窗体的任何位置拖放

当然,迭代控件将工作,它不需要太多代码:

    public Form1() {
        InitializeComponent();
        WireDragDrop(this.Controls);
    }
    private void WireDragDrop(Control.ControlCollection ctls) {
        foreach (Control ctl in ctls) {
            ctl.AllowDrop = true;
            ctl.DragEnter += ctl_DragEnter;
            ctl.DragDrop += ctl_DragDrop;
            WireDragDrop(ctl.Controls);
        }
    }
    void ctl_DragDrop(object sender, DragEventArgs e) {
        // etc..
    }
    void ctl_DragEnter(object sender, DragEventArgs e) {
        // etc..
    }

如果你仍然不喜欢这种方法,那就使用一个用户总是会命中的可识别的单一掉落目标。可以是一个简单的标签,上面写着"Drop here"

我不确定你对你的表单有什么样的控制。但我已经用Button、GroupBox、PictureBox和TextBox进行了测试。所有这些控件默认都有AllowDrop = false。我可以从外部拖拽一些东西到表单上。DragDrop发射成功。一切都很好。你到底有什么问题?我猜你的控件有AllowDrop = true

DragDrop事件没有被触发的情况下(我认为只有在目标是AllowDrop = true的控制之一时才会发生)。我认为以下方法可能有效。但如果目标是AllowDrop = true控件之一,则效果图标将消失。

public Form1(){
    InitializeComponents();
    t.Interval = 1;
    t.Tick += Tick;
}
IDataObject data;
Timer t = new Timer();
int i = 0;
private void Tick(object sender, EventArgs e)
{
     Text = (i++).ToString();
     if (ClientRectangle.Contains(PointToClient(new Point(MousePosition.X, MousePosition.Y))) && MouseButtons == MouseButtons.None)
     {
        t.Stop();
        if (data != null)
        {
           //Process data here
           //-----------------               
           data = null;
        }                                
     }
     else if (MouseButtons == MouseButtons.None)
     {
        data = null;
        t.Stop();
     }
}
private void Form1_DragEnter(object sender, DragEventArgs e)
{
   e.Effect = e.AllowedEffect;
   if (data == null)
   {
       data = e.Data;
       t.Start();
   }
}

并且我认为您可能必须在所有控件中使用循环来添加适当的事件处理程序。没有比这更好的办法了。

Drop事件

string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
        foreach (string file in files) Console.WriteLine(file);

DragEnter事件。

if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effects = DragDropEffects.Copy;