【问题标题】:Allow DragDrop anywhere in a form允许在表单中的任意位置拖放
【发布时间】:2013-06-09 22:15:13
【问题描述】:

有没有办法允许在充满控件的表单中任意位置拖放?

这个想法是允许用户将文件拖到表单中的任何位置以“加载”它。除了这个,我不需要任何其他 DragDrop 行为。

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

一个想法是在DragEnter 上显示一个topmost 面板并在那里处理DragDrop 事件,但我想知道我是否错过了一些明显的东西,因为我在该领域的经验很少。

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

【问题讨论】:

    标签: c# winforms drag-and-drop


    【解决方案1】:

    当然,迭代控件会起作用,它不需要太多代码:

        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..
        }
    

    如果您仍然不喜欢这种方法,请使用用户始终会击中的可识别的单次放置目标。可以像“放在这里”的标签一样简单。

    【讨论】:

      【解决方案2】:

      我不确定您对表单有哪些类型的控制。但是我用一个按钮、一个组框、一个图片框和一个文本框进行了测试。所有这些控件默认都有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();
         }
      }
      

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

      【讨论】:

        【解决方案3】:

        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;
        

        【讨论】:

        • 在一个充满控件的表单中,这应该在哪里?在表单的放置事件中还是在每个控件中?问题更多是关于如何获得有关事件的通知,而不是实际做某事。
        猜你喜欢
        • 1970-01-01
        • 2015-02-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-08
        • 1970-01-01
        • 1970-01-01
        • 2019-05-28
        • 1970-01-01
        相关资源
        最近更新 更多