// Copyright � 2006 by Christoph Richner. All rights are reserved. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // // website http://www.raccoom.net, email support@raccoom.net, msn chrisdarebell@msn.com using System; using System.Windows.Forms; using System.Drawing; namespace Raccoom.Windows.Forms { /// <summary> /// Drag'n'Drop Hyperlink from Webbrowser to a control. /// </summary> public class TreeViewDragDropHyperlink { #region fields #region delegate public class UrlDragDropEventArgs : EventArgs { private Uri _uri; public UrlDragDropEventArgs(Uri uri) { this._uri = uri; } public Uri Uri { get { return _uri; } } } public delegate void UrlDragDropDelegate(object sender, UrlDragDropEventArgs e); #endregion public UrlDragDropDelegate UrlDragDrop; #endregion #region constructors public TreeViewDragDropHyperlink(System.Windows.Forms.Control control) { System.Diagnostics.Debug.Assert(control!=null); // control.AllowDrop = true; control.DragEnter += new System.Windows.Forms.DragEventHandler(OnDragEnter); control.DragDrop +=new System.Windows.Forms.DragEventHandler(OnDragDrop); } #endregion #region public interface /// <summary> /// Allow draging of UniformResourceLocator (Hyperlinks) /// </summary> private void OnDragEnter(object sender, System.Windows.Forms.DragEventArgs e) { if(e.Data.GetData("UniformResourceLocator",true)!=null) { e.Effect = System.Windows.Forms.DragDropEffects.Link; } else { e.Effect = System.Windows.Forms.DragDropEffects.None; } } /// <summary> /// If valid UniformResourceLocator was dropped, load it /// </summary> private void OnDragDrop(object sender, System.Windows.Forms.DragEventArgs e) { // FileContents // UniformResourceLocator // try { string url = e.Data.GetData(typeof(string)) as string; // some browser deliver url and text in UniformResourceLocator string[] tokens =url.Split('\n'); if(tokens.Length>1) { url= tokens[0]; } // if(UrlDragDrop!=null) UrlDragDrop(this, new UrlDragDropEventArgs(new Uri(url))); } catch (System.Exception ex) { System.Diagnostics.Trace.WriteLine(ex.Message); } } #endregion } /// <summary> /// Mimic the "Windows" (tm) way and implement a placeholder letting the user know where the item will be dropped. /// </summary> /// <remarks>Copyright by Gabe Anguiano, http://www.codeproject.com/cs/miscctrl/TreeViewReArr.asp</remarks> public class TreeViewDragDropRearrange { #region fields private string _nodeMap; private TreeView _treeView; #endregion #region public constructors public TreeViewDragDropRearrange(TreeView treeView) { System.Diagnostics.Debug.Assert(treeView!=null); // _treeView = treeView; _treeView.MouseDown += new MouseEventHandler(treeView1_MouseDown); _treeView.ItemDrag += new ItemDragEventHandler(treeView1_ItemDrag); _treeView.DragEnter += new DragEventHandler(treeView1_DragEnter); _treeView.DragDrop += new DragEventHandler(treeView1_DragDrop); _treeView.DragOver += new DragEventHandler(treeView1_DragOver); } #endregion #region private interface private void treeView1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) { _treeView.SelectedNode = _treeView.GetNodeAt(e.X, e.Y); } private void treeView1_ItemDrag(object sender, System.Windows.Forms.ItemDragEventArgs e) { _treeView.DoDragDrop(e.Item, DragDropEffects.Move); } private void treeView1_DragEnter(object sender, System.Windows.Forms.DragEventArgs e) { e.Effect = DragDropEffects.Move; } private void treeView1_DragDrop(object sender, System.Windows.Forms.DragEventArgs e) { if(e.Data.GetDataPresent("System.Windows.Forms.TreeNode", false) && _nodeMap != "") { TreeNode MovingNode = (TreeNode)e.Data.GetData("System.Windows.Forms.TreeNode"); string[] NodeIndexes = _nodeMap.Split('|'); TreeNodeCollection InsertCollection = _treeView.Nodes; for(int i = 0; i < NodeIndexes.Length - 1; i++) { InsertCollection = InsertCollection[Int32.Parse(NodeIndexes[i])].Nodes; } if(InsertCollection != null) { InsertCollection.Insert(Int32.Parse(NodeIndexes[NodeIndexes.Length - 1]), (TreeNode)MovingNode.Clone()); _treeView.SelectedNode = InsertCollection[Int32.Parse(NodeIndexes[NodeIndexes.Length - 1])]; MovingNode.Remove(); } } } private void treeView1_DragOver(object sender, System.Windows.Forms.DragEventArgs e) { TreeNode NodeOver = _treeView.GetNodeAt(_treeView.PointToClient(Cursor.Position)); TreeNode NodeMoving = (TreeNode)e.Data.GetData("System.Windows.Forms.TreeNode"); // A bit long, but to summarize, process the following coe only if the nodeover is null // and either the nodeover is not the same thing as nodemoving UNLESSS nodeover happens // to be the last node in the branch (so we can allow drag & drop below a parent branch) if(NodeOver != null && (NodeOver != NodeMoving || (NodeOver.Parent != null && NodeOver.Index == (NodeOver.Parent.Nodes.Count - 1)))) { int OffsetY = _treeView.PointToClient(Cursor.Position).Y - NodeOver.Bounds.Top; int NodeOverImageWidth = _treeView.ImageList.Images[NodeOver.ImageIndex].Size.Width + 8; Graphics g = _treeView.CreateGraphics(); // Image index of 1 is the non-folder icon if(NodeOver.ImageIndex == 1) { #region Standard Node if(OffsetY < (NodeOver.Bounds.Height / 2)) { //this.lblDebug.Text = "top"; #region If NodeOver is a child then cancel TreeNode tnParadox = NodeOver; while(tnParadox.Parent != null) { if(tnParadox.Parent == NodeMoving) { this._nodeMap = ""; return; } tnParadox = tnParadox.Parent; } #endregion #region Store the placeholder info into a pipe delimited string TreeNode tnPlaceholderInfo = NodeOver; string NewNodeMap = ((int)NodeOver.Index).ToString(); while(tnPlaceholderInfo.Parent != null) { tnPlaceholderInfo = tnPlaceholderInfo.Parent; NewNodeMap = tnPlaceholderInfo.Index + "|" + NewNodeMap; } if(NewNodeMap == this._nodeMap) return; else this._nodeMap = NewNodeMap; #endregion #region Clear placeholders above and below _treeView.Refresh(); #endregion #region Draw the placeholders int LeftPos, RightPos; LeftPos = NodeOver.Bounds.Left - NodeOverImageWidth; RightPos = _treeView.Width - 4; Point[] LeftTriangle = new Point[5]{ new Point(LeftPos, NodeOver.Bounds.Top - 4), new Point(LeftPos, NodeOver.Bounds.Top + 4), new Point(LeftPos + 4, NodeOver.Bounds.Y), new Point(LeftPos + 4, NodeOver.Bounds.Top - 1), new Point(LeftPos, NodeOver.Bounds.Top - 5)}; Point[] RightTriangle = new Point[5]{ new Point(RightPos, NodeOver.Bounds.Top - 4), new Point(RightPos, NodeOver.Bounds.Top + 4), new Point(RightPos - 4, NodeOver.Bounds.Y), new Point(RightPos - 4, NodeOver.Bounds.Top - 1), new Point(RightPos, NodeOver.Bounds.Top - 5)}; g.FillPolygon(System.Drawing.Brushes.Black, LeftTriangle); g.FillPolygon(System.Drawing.Brushes.Black, RightTriangle); g.DrawLine(new System.Drawing.Pen(Color.Black, 2), new Point(LeftPos, NodeOver.Bounds.Top), new Point(RightPos, NodeOver.Bounds.Top)); #endregion } else { //this.lblDebug.Text = "bottom"; #region If NodeOver is a child then cancel TreeNode tnParadox = NodeOver; while(tnParadox.Parent != null) { if(tnParadox.Parent == NodeMoving) { this._nodeMap = ""; return; } tnParadox = tnParadox.Parent; } #endregion #region Allow drag drop to parent branches TreeNode ParentDragDrop = null; // If the node the mouse is over is the last node of the branch we should allow // the ability to drop the "nodemoving" node BELOW the parent node if(NodeOver.Parent != null && NodeOver.Index == (NodeOver.Parent.Nodes.Count - 1)) { int XPos = _treeView.PointToClient(Cursor.Position).X; if(XPos < NodeOver.Bounds.Left) { ParentDragDrop = NodeOver.Parent; while(true) { if(XPos > (ParentDragDrop.Bounds.Left - _treeView.ImageList.Images[ParentDragDrop.ImageIndex].Size.Width)) break; if(ParentDragDrop.Parent != null) ParentDragDrop = ParentDragDrop.Parent; else break; } } } #endregion #region Store the placeholder info into a pipe delimited string // Since we are in a special case here, use the ParentDragDrop node as the current "nodeover" TreeNode tnPlaceholderInfo; if(ParentDragDrop != null) tnPlaceholderInfo = ParentDragDrop; else tnPlaceholderInfo = NodeOver; string NewNodeMap = ((int)tnPlaceholderInfo.Index + 1).ToString(); while(tnPlaceholderInfo.Parent != null) { tnPlaceholderInfo = tnPlaceholderInfo.Parent; NewNodeMap = tnPlaceholderInfo.Index + "|" + NewNodeMap; } if(NewNodeMap == this._nodeMap) return; else this._nodeMap = NewNodeMap; #endregion #region Clear placeholders above and below _treeView.Refresh(); #endregion #region Draw the placeholders // Once again, we are not dragging to node over, draw the placeholder using the ParentDragDrop bounds int LeftPos, RightPos; if(ParentDragDrop != null) LeftPos = ParentDragDrop.Bounds.Left - (_treeView.ImageList.Images[ParentDragDrop.ImageIndex].Size.Width + 8); else LeftPos = NodeOver.Bounds.Left - NodeOverImageWidth; RightPos = _treeView.Width - 4; Point[] LeftTriangle = new Point[5]{ new Point(LeftPos, NodeOver.Bounds.Bottom - 4), new Point(LeftPos, NodeOver.Bounds.Bottom + 4), new Point(LeftPos + 4, NodeOver.Bounds.Bottom), new Point(LeftPos + 4, NodeOver.Bounds.Bottom - 1), new Point(LeftPos, NodeOver.Bounds.Bottom - 5)}; Point[] RightTriangle = new Point[5]{ new Point(RightPos, NodeOver.Bounds.Bottom - 4), new Point(RightPos, NodeOver.Bounds.Bottom + 4), new Point(RightPos - 4, NodeOver.Bounds.Bottom), new Point(RightPos - 4, NodeOver.Bounds.Bottom - 1), new Point(RightPos, NodeOver.Bounds.Bottom - 5)}; g.FillPolygon(System.Drawing.Brushes.Black, LeftTriangle); g.FillPolygon(System.Drawing.Brushes.Black, RightTriangle); g.DrawLine(new System.Drawing.Pen(Color.Black, 2), new Point(LeftPos, NodeOver.Bounds.Bottom), new Point(RightPos, NodeOver.Bounds.Bottom)); #endregion } #endregion } else { #region Folder Node if(OffsetY < (NodeOver.Bounds.Height / 3)) { //this.lblDebug.Text = "folder top"; #region If NodeOver is a child then cancel TreeNode tnParadox = NodeOver; while(tnParadox.Parent != null) { if(tnParadox.Parent == NodeMoving) { this._nodeMap = ""; return; } tnParadox = tnParadox.Parent; } #endregion #region Store the placeholder info into a pipe delimited string TreeNode tnPlaceholderInfo = NodeOver; string NewNodeMap = ((int)NodeOver.Index).ToString(); while(tnPlaceholderInfo.Parent != null) { tnPlaceholderInfo = tnPlaceholderInfo.Parent; NewNodeMap = tnPlaceholderInfo.Index + "|" + NewNodeMap; } if(NewNodeMap == this._nodeMap) return; else this._nodeMap = NewNodeMap; #endregion #region Clear placeholders above and below _treeView.Refresh(); #endregion #region Draw the placeholders int LeftPos, RightPos; LeftPos = NodeOver.Bounds.Left - NodeOverImageWidth; RightPos = _treeView.Width - 4; Point[] LeftTriangle = new Point[5]{ new Point(LeftPos, NodeOver.Bounds.Top - 4), new Point(LeftPos, NodeOver.Bounds.Top + 4), new Point(LeftPos + 4, NodeOver.Bounds.Y), new Point(LeftPos + 4, NodeOver.Bounds.Top - 1), new Point(LeftPos, NodeOver.Bounds.Top - 5)}; Point[] RightTriangle = new Point[5]{ new Point(RightPos, NodeOver.Bounds.Top - 4), new Point(RightPos, NodeOver.Bounds.Top + 4), new Point(RightPos - 4, NodeOver.Bounds.Y), new Point(RightPos - 4, NodeOver.Bounds.Top - 1), new Point(RightPos, NodeOver.Bounds.Top - 5)}; g.FillPolygon(System.Drawing.Brushes.Black, LeftTriangle); g.FillPolygon(System.Drawing.Brushes.Black, RightTriangle); g.DrawLine(new System.Drawing.Pen(Color.Black, 2), new Point(LeftPos, NodeOver.Bounds.Top), new Point(RightPos, NodeOver.Bounds.Top)); #endregion } else if((NodeOver.Parent != null && NodeOver.Index == 0) && (OffsetY > (NodeOver.Bounds.Height - (NodeOver.Bounds.Height / 3)))) { //this.lblDebug.Text = "folder bottom"; #region If NodeOver is a child then cancel TreeNode tnParadox = NodeOver; while(tnParadox.Parent != null) { if(tnParadox.Parent == NodeMoving) { this._nodeMap = ""; return; } tnParadox = tnParadox.Parent; } #endregion #region Store the placeholder info into a pipe delimited string TreeNode tnPlaceholderInfo = NodeOver; string NewNodeMap = ((int)NodeOver.Index + 1).ToString(); while(tnPlaceholderInfo.Parent != null) { tnPlaceholderInfo = tnPlaceholderInfo.Parent; NewNodeMap = tnPlaceholderInfo.Index + "|" + NewNodeMap; } if(NewNodeMap == this._nodeMap) return; else this._nodeMap = NewNodeMap; #endregion #region Clear placeholders above and below _treeView.Refresh(); #endregion #region Draw the placeholders int LeftPos, RightPos; LeftPos = NodeOver.Bounds.Left - NodeOverImageWidth; RightPos = _treeView.Width - 4; Point[] LeftTriangle = new Point[5]{ new Point(LeftPos, NodeOver.Bounds.Bottom - 4), new Point(LeftPos, NodeOver.Bounds.Bottom + 4), new Point(LeftPos + 4, NodeOver.Bounds.Bottom), new Point(LeftPos + 4, NodeOver.Bounds.Bottom - 1), new Point(LeftPos, NodeOver.Bounds.Bottom - 5)}; Point[] RightTriangle = new Point[5]{ new Point(RightPos, NodeOver.Bounds.Bottom - 4), new Point(RightPos, NodeOver.Bounds.Bottom + 4), new Point(RightPos - 4, NodeOver.Bounds.Bottom), new Point(RightPos - 4, NodeOver.Bounds.Bottom - 1), new Point(RightPos, NodeOver.Bounds.Bottom - 5)}; g.FillPolygon(System.Drawing.Brushes.Black, LeftTriangle); g.FillPolygon(System.Drawing.Brushes.Black, RightTriangle); g.DrawLine(new System.Drawing.Pen(Color.Black, 2), new Point(LeftPos, NodeOver.Bounds.Bottom), new Point(RightPos, NodeOver.Bounds.Bottom)); #endregion } else { //this.lblDebug.Text = "folder over"; if(NodeOver.Nodes.Count > 0) { NodeOver.Expand(); //this.Refresh(); } else { #region Prevent the node from being dragged onto itself if(NodeMoving == NodeOver) return; #endregion #region If NodeOver is a child then cancel TreeNode tnParadox = NodeOver; while(tnParadox.Parent != null) { if(tnParadox.Parent == NodeMoving) { this._nodeMap = ""; return; } tnParadox = tnParadox.Parent; } #endregion #region Store the placeholder info into a pipe delimited string TreeNode tnPlaceholderInfo = NodeOver; string NewNodeMap = ((int)NodeOver.Index).ToString(); while(tnPlaceholderInfo.Parent != null) { tnPlaceholderInfo = tnPlaceholderInfo.Parent; NewNodeMap = tnPlaceholderInfo.Index + "|" + NewNodeMap; } NewNodeMap = NewNodeMap + "|0"; if(NewNodeMap == this._nodeMap) return; else this._nodeMap = NewNodeMap; #endregion #region Clear placeholders above and below _treeView.Refresh(); #endregion #region Draw the "add to folder" placeholder int RightPos = NodeOver.Bounds.Right + 6; Point[] RightTriangle = new Point[5]{ new Point(RightPos, NodeOver.Bounds.Y + (NodeOver.Bounds.Height / 2) + 4), new Point(RightPos, NodeOver.Bounds.Y + (NodeOver.Bounds.Height / 2) + 4), new Point(RightPos - 4, NodeOver.Bounds.Y + (NodeOver.Bounds.Height / 2)), new Point(RightPos - 4, NodeOver.Bounds.Y + (NodeOver.Bounds.Height / 2) - 1), new Point(RightPos, NodeOver.Bounds.Y + (NodeOver.Bounds.Height / 2) - 5)}; _treeView.Refresh(); g.FillPolygon(System.Drawing.Brushes.Black, RightTriangle); #endregion } } #endregion } } } #endregion } }
By viewing downloads associated with this article you agree to the Terms of use and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.
This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)
Math Primers for Programmers