防止拖放到当前控件之外(TreeView 中的 TreeNodes)

Posted

技术标签:

【中文标题】防止拖放到当前控件之外(TreeView 中的 TreeNodes)【英文标题】:Prevent drag and drop outside of the current control (TreeNodes in a TreeView) 【发布时间】:2012-04-09 17:43:51 【问题描述】:

我正在维护一个 Windows 应用程序,该应用程序在一个窗口中具有多个表单(form1form2form3)。目前,我将其他 form2form3 视为黑匣子。在 form1 中,我有一个 TreeView,我正在该 TreeView 中实现拖放功能。 如何防止在 form1 控件之外放置?

我正在实现 3 个事件处理程序:

private void treeView_ItemDrag (...)

    DoDragDrop(e.Item, DragDropEffects.Move);
 

private void treeView_DragEvent (...) 

    e.Effect = DragDropEffects.Move;


private void treeView_DragDrop (...)

    //the node move logic here

form2form3 之间有拖放关系,所以当我将节点从form1 拖到form3 时,默认情况下它允许移动(坏)。我希望能够从 form1 控制代码中防止这种情况发生。

如何防止在form1 控件之外的操作?我查看了 _DragLeave 事件,但不确定如何在没有 DragEventArgs 的情况下控制操作。

【问题讨论】:

【参考方案1】:

Cursor 对象中有一个鲜为人知的属性,它可以将鼠标移动限制在某个矩形上。

this 作为 Form1 的全局变量

   Rectangle _originalClip;

这在您的 Form1_Load 事件中

  _originalClip = Cursor.Clip;

这可能在您的 treeView.ItemDrag 中,强制光标在 form1 客户区域内

   Cursor.Clip = form1.RectangleToScreen(form1.ClientRectangle);

现在您需要恢复原始剪辑区域。一个好地方将在 treeView.DragDrop 中。但为了安全起见,也要放在 Form1_Closing 事件中

   Cursor.Clip = _originalClip;

【讨论】:

谢谢史蒂夫,这看起来是一个简单的解决方案,我会试试的。【参考方案2】:

您可以检查鼠标拖动动作是否超出允许区域,如果是,则取消拖动动作。

MSDN 中有一个很好的示例,它为此目的使用了 QueryContinueDrag 事件。我认为您可以在解决方案的基础上使用它。

链接:DragAction Enumeration

【讨论】:

谢谢 jjokela,我会试一试的。【参考方案3】:

我知道这是一个老话题,但由于我从来没有找到一个很好的答案来解决如何防止将控件拖到面板之外,所以我想我会提出我放在一起的解决方案。我使用了上面的一些技巧和我自己的一些工作。

private void Form1_Load(object sender, EventArgs e)
        
            _originalClip = Cursor.Clip;
        

        private void pb_MouseMove(object sender, MouseEventArgs e)
        
            PictureBox pb = (PictureBox)sender;
            if (e.Button == MouseButtons.Left)
            
                Size sz = new Size(panel1.RectangleToScreen(panel1.ClientRectangle).Width - (pb.Width), panel1.RectangleToScreen(panel1.ClientRectangle).Height - (pb.Height));
                Point loc = new Point(panel1.RectangleToScreen(panel1.ClientRectangle).X + (pb.Width / 2), panel1.RectangleToScreen(panel1.ClientRectangle).Y + (pb.Height / 2));
                Rectangle rct = new Rectangle(loc, sz);
                Cursor.Clip = rct;
                pb.Left += (e.X - x);
                pb.Top += (e.Y - y);
            
        
        private void pb_MouseUp(object sender, MouseEventArgs e)
        
            Cursor.Clip = _originalClip;
        

它的作用是使用 Cursor.Clip 方法和一个 Rectangle 对象,它的大小设置为包含一堆图片框(代码中的“pb”)的面板(代码中的“panel1”)的大小.新矩形的大小设置为父面板减去 Picturebox 的宽度和高度,它的位置设置为 panel1 的位置减去 Picturebox 的宽度和高度的一半。这为您提供了一个矩形,该矩形将限制 Picturebox 在面板之外成为药物。

【讨论】:

哇,7 年后的新答案……应该会给你一些徽章。不幸的是,我不再准备测试您的解决方案,但希望有人发现您的贡献有用。

以上是关于防止拖放到当前控件之外(TreeView 中的 TreeNodes)的主要内容,如果未能解决你的问题,请参考以下文章

delphi中的treeview控件如何取到选择节点的索引号?

treeview控件使用详解

wpf中如何实现控件的拖拽

当我在 JavaScript 中将图像拖放到 Chrome 浏览器上时,如何防止打开新标签页?

如何将图片从资源管理器拖放到 WPF 控件上?

为啥 WinForms 中的 TreeView 会意外崩溃?