// // OnDragLeave event handler. Updates the dragged node's ghost image's position. // protected override void OnDragLeave(EventArgs e) { base.OnDragLeave(e); DragHelper.ImageList_DragLeave(Handle); // Disable timer for scrolling dragged item _timer.Enabled = false; }
// // OnDragEnter event handler. Updates the dragged node's ghost image's position. // protected override void OnDragEnter(DragEventArgs drgevent) { base.OnDragEnter(drgevent); DragHelper.ImageList_DragEnter(Handle, drgevent.X - Left, drgevent.Y - Top); // Enable timer for scrolling dragged item _timer.Enabled = true; }
// // Timer tick. Updates scrolling of the TreeView // private void timer_Tick(object sender, EventArgs e) { // get node at mouse position Point pt = PointToClient(MousePosition); TreeNode node = GetNodeAt(pt); if (node == null) { return; } // if mouse is near to the top, scroll up if (pt.Y < 30) { // set actual node to the upper one if (node.PrevVisibleNode != null) { node = node.PrevVisibleNode; // hide drag image DragHelper.ImageList_DragShowNolock(false); // scroll and refresh node.EnsureVisible(); Refresh(); // show drag image DragHelper.ImageList_DragShowNolock(true); } } // if mouse is near to the bottom, scroll down else if (pt.Y > Size.Height - 30) { if (node.NextVisibleNode != null) { node = node.NextVisibleNode; DragHelper.ImageList_DragShowNolock(false); node.EnsureVisible(); Refresh(); DragHelper.ImageList_DragShowNolock(true); } } }
// // OnDragDrop event handler. Ends a node dragging // protected override void OnDragDrop(DragEventArgs drgevent) { base.OnDragDrop(drgevent); // Cancel if no node is being dragged if (_draggedNode == null) { return; } // Unlock updates DragHelper.ImageList_DragLeave(Handle); if (drgevent.Effect == DragDropEffects.None) { // Set drag node and temp drop node to null _draggedNode = null; _tempDropNode = null; // Disable scroll timer _timer.Enabled = false; return; } // Get drop node TreeNode dropNode = GetNodeAt(PointToClient(new Point(drgevent.X, drgevent.Y))); // Launch the feedback for the drag operation TreeViewNodeDragEventArgs evArgs = new TreeViewNodeDragEventArgs(TreeViewNodeDragEventType.DragEnd, TreeViewNodeDragEventBehavior.PlaceInside, _draggedNode, dropNode); if (DragOperation != null) { DragOperation(evArgs); // Cancel the operation if the user specified so if (evArgs.Cancel) { return; } } // If drop node isn't equal to drag node, add drag node as child of drop node if (_draggedNode != dropNode) { // Remove drag node from parent if (_draggedNode.Parent == null) { Nodes.Remove(_draggedNode); } else { _draggedNode.Parent.Nodes.Remove(_draggedNode); } // Place the dragged node before or after the target node depending on mouse position if (evArgs.EventBehavior == TreeViewNodeDragEventBehavior.PlaceBeforeOrAfterAuto) { // Get drop node Point mouseP = PointToClient(MousePosition); // Figure out whether the node should be added uder or over the pointed item by checking if the mouse is under or over the middle of the item evArgs.EventBehavior = mouseP.Y > dropNode.Bounds.Y + dropNode.Bounds.Height / 2 ? TreeViewNodeDragEventBehavior.PlaceAfter : TreeViewNodeDragEventBehavior.PlaceBefore; } // Place the dragged node before the target node if (evArgs.EventBehavior == TreeViewNodeDragEventBehavior.PlaceBefore) { // Add drag node before drop node if (dropNode.Parent != null) { dropNode.Parent.Nodes.Insert(dropNode.Index, _draggedNode); } else { Nodes.Insert(dropNode.Index, _draggedNode); } SelectedNode = _draggedNode; } // Place the dragged node after the target node if (evArgs.EventBehavior == TreeViewNodeDragEventBehavior.PlaceAfter) { // Add drag node after drop node if (dropNode.Parent != null) { dropNode.Parent.Nodes.Insert(dropNode.Index + 1, _draggedNode); } else { Nodes.Insert(dropNode.Index + 1, _draggedNode); } SelectedNode = _draggedNode; } // Place the dragged node inside the target node if (evArgs.EventBehavior == TreeViewNodeDragEventBehavior.PlaceInside) { // Add drag node to drop node dropNode.Nodes.Add(_draggedNode); dropNode.ExpandAll(); } // Launch the feedback for the drag operation evArgs = new TreeViewNodeDragEventArgs(TreeViewNodeDragEventType.AfterDragEnd, evArgs.EventBehavior, _draggedNode, dropNode); DragOperation?.Invoke(evArgs); // Set drag node and temp drop node to null _draggedNode = null; _tempDropNode = null; // Disable scroll timer _timer.Enabled = false; } }
// // OnDragOver event handler. Updates the dragged node's ghost image's position // protected override void OnDragOver(DragEventArgs drgevent) { base.OnDragOver(drgevent); // Cancel if no node is being dragged if (_draggedNode == null) { return; } // Compute drag position and move image var findForm = FindForm(); if (findForm != null) { Point formP = findForm.PointToClient(new Point(drgevent.X, drgevent.Y)); DragHelper.ImageList_DragMove(formP.X - Left, formP.Y - Top); } // Get actual drop node TreeNode dropNode = GetNodeAt(PointToClient(new Point(drgevent.X, drgevent.Y))); if (dropNode == null) { drgevent.Effect = DragDropEffects.None; return; } TreeViewNodeDragEventArgs evArgs = new TreeViewNodeDragEventArgs(TreeViewNodeDragEventType.DragOver, TreeViewNodeDragEventBehavior.PlaceInside, _draggedNode, dropNode); if (DragOperation != null) { DragOperation(evArgs); // Cancel the operation if the user specified so if (evArgs.Cancel) { drgevent.Effect = DragDropEffects.None; OnDragDrop(drgevent); return; } if (!evArgs.Allow) { return; } } drgevent.Effect = DragDropEffects.Move; // Dissalow the drag here if (!evArgs.Allow) { drgevent.Effect = DragDropEffects.None; } // if mouse is on a new node select it if (_tempDropNode != dropNode) { DragHelper.ImageList_DragShowNolock(false); SelectedNode = dropNode; DragHelper.ImageList_DragShowNolock(true); _tempDropNode = dropNode; } // Avoid that drop node is child of drag node TreeNode tmpNode = dropNode; while (tmpNode.Parent != null) { if (tmpNode.Parent == _draggedNode) { drgevent.Effect = DragDropEffects.None; } tmpNode = tmpNode.Parent; } }
// // OnItemDrag event handler. Starts dragging a node // protected override void OnItemDrag(ItemDragEventArgs e) { base.OnItemDrag(e); SelectedNode = (TreeNode)e.Item; TreeViewNodeDragEventArgs evArgs = new TreeViewNodeDragEventArgs(TreeViewNodeDragEventType.DragStart, TreeViewNodeDragEventBehavior.PlaceInside, (TreeNode)e.Item, null); if (DragOperation != null) { DragOperation(evArgs); // Cancel the operation if the user specified so if (evArgs.Cancel) { return; } } // Get drag node and select it _draggedNode = (TreeNode)e.Item; SelectedNode = evArgs.DraggedNode; // Reset image list used for drag image _imageListDrag.Images.Clear(); _imageListDrag.ImageSize = new Size(_draggedNode.Bounds.Size.Width + Indent, _draggedNode.Bounds.Height); //// Create new bitmap // This bitmap will contain the tree node image to be dragged Bitmap bmp = new Bitmap(_draggedNode.Bounds.Width + Indent, _draggedNode.Bounds.Height); SolidBrush brush = new SolidBrush(ForeColor); // Get graphics from bitmap Graphics gfx = Graphics.FromImage(bmp); gfx.SmoothingMode = SmoothingMode.HighQuality; gfx.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; // Draw node icon into the bitmap if (_draggedNode.ImageKey == "") { gfx.DrawImage(ImageList.Images[_draggedNode.ImageIndex], 0, 0); } else { if (ImageList?.Images[_draggedNode.ImageKey] != null) { gfx.DrawImage(ImageList.Images[_draggedNode.ImageKey], 0, 0); } } // Draw node label into bitmap gfx.DrawString(_draggedNode.Text, Font, brush, Indent, 1.0f); gfx.Flush(); gfx.Dispose(); brush.Dispose(); // Add bitmap to imagelist _imageListDrag.Images.Add(bmp); // Get mouse position in client coordinates Point p = PointToClient(MousePosition); // Compute delta between mouse position and node bounds int dx = p.X + Indent - _draggedNode.Bounds.Left; int dy = p.Y - _draggedNode.Bounds.Top; // Begin dragging image if (DragHelper.ImageList_BeginDrag(_imageListDrag.Handle, 0, dx, dy)) { // Begin dragging DoDragDrop(bmp, DragDropEffects.Move); // End dragging image DragHelper.ImageList_EndDrag(); } }