634 lines
21 KiB
C#
634 lines
21 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.Drawing;
|
|
using System.Text;
|
|
using System.Windows.Forms;
|
|
using System.Runtime.InteropServices; // For DragHelper
|
|
using System.Reflection;
|
|
using VEPROMS.CSLA.Library;
|
|
|
|
namespace Volian.Controls.Library
|
|
{
|
|
public delegate void vlnTreeViewEvent(object sender, vlnTreeEventArgs args);
|
|
public delegate bool vlnTreeViewBoolEvent(object sender, vlnTreeEventArgs args);
|
|
public delegate TreeNode vlnTreeViewTreeNodeEvent(object sender, vlnTreeEventArgs args);
|
|
//public delegate void vlnTreeViewDDEvent(object sender, System.Windows.Forms.DragEventArgs args);
|
|
public partial class vlnTreeEventArgs
|
|
{
|
|
#region Business Methods
|
|
private TreeNode _Node;
|
|
public TreeNode Node
|
|
{
|
|
get { return _Node; }
|
|
set { _Node = value; }
|
|
}
|
|
private TreeNode _Destination=null;
|
|
public TreeNode Destination
|
|
{
|
|
get { return _Destination; }
|
|
set { _Destination = value; }
|
|
}
|
|
private int _Index;
|
|
public int Index
|
|
{
|
|
get { return _Index; }
|
|
set { _Index = value; }
|
|
}
|
|
#endregion
|
|
#region Factory Methods
|
|
private vlnTreeEventArgs() { ;}
|
|
public vlnTreeEventArgs(TreeNode node)
|
|
{
|
|
_Node = node;
|
|
}
|
|
public vlnTreeEventArgs(TreeNode node, TreeNode destination, int index)
|
|
{
|
|
_Node = node;
|
|
_Destination = destination;
|
|
_Index = index;
|
|
}
|
|
#endregion
|
|
}
|
|
public partial class vlnTreeView : TreeView
|
|
{
|
|
private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
|
#region Events
|
|
public event vlnTreeViewEvent NodeDragDrop;
|
|
private void OnNodeDragDrop(object sender, vlnTreeEventArgs args)
|
|
{
|
|
if (NodeDragDrop != null) NodeDragDrop(sender, args);
|
|
}
|
|
public event vlnTreeViewEvent NodeMove;
|
|
private void OnNodeMove(object sender, vlnTreeEventArgs args)
|
|
{
|
|
if (NodeMove != null) NodeMove(sender, args);
|
|
}
|
|
public event vlnTreeViewEvent NodeCopy;
|
|
private void OnNodeCopy(object sender, vlnTreeEventArgs args)
|
|
{
|
|
if (NodeCopy != null) NodeCopy(sender, args);
|
|
}
|
|
public event vlnTreeViewBoolEvent NodeDelete;
|
|
private bool OnNodeDelete(object sender, vlnTreeEventArgs args)
|
|
{
|
|
bool result = true;
|
|
if (NodeDelete != null) result = NodeDelete(sender, args);
|
|
return result;
|
|
}
|
|
public event vlnTreeViewTreeNodeEvent NodeNew;
|
|
private TreeNode OnNodeNew(object sender, vlnTreeEventArgs args)
|
|
{
|
|
if (NodeNew != null) return NodeNew(sender, args);
|
|
else return new TreeNode("New Item");
|
|
}
|
|
public event vlnTreeViewEvent NodeProperties;
|
|
private void OnNodeProperties(object sender, vlnTreeEventArgs args)
|
|
{
|
|
if (NodeProperties != null) NodeProperties(sender, args);
|
|
}
|
|
public event vlnTreeViewEvent NodeSelectionChange;
|
|
private void OnNodeSelectionChange(object sender, vlnTreeEventArgs args)
|
|
{
|
|
if (NodeSelectionChange != null) NodeSelectionChange(sender, args);
|
|
}
|
|
#endregion
|
|
#region Business Methods
|
|
ImageList _dragImageList = new ImageList();
|
|
#endregion
|
|
#region Constructors
|
|
public vlnTreeView()
|
|
{
|
|
InitializeComponent();
|
|
this.AllowDrop = true;
|
|
DragHelper.InitCommonControls();
|
|
this.ItemDrag += new ItemDragEventHandler(tv_ItemDrag);
|
|
this.DragDrop += new DragEventHandler(tv_DragDrop);
|
|
this.DragEnter += new DragEventHandler(tv_DragEnter);
|
|
this.DragLeave += new EventHandler(tv_DragLeave);
|
|
this.DragOver += new DragEventHandler(tv_DragOver);
|
|
this.MouseDown += new MouseEventHandler(tv_MouseDown);
|
|
base.AfterSelect += new TreeViewEventHandler(tv_AfterSelect);
|
|
}
|
|
private void tv_AfterSelect(object sender, TreeViewEventArgs e)
|
|
{
|
|
OnNodeSelectionChange(sender, new vlnTreeEventArgs(e.Node));
|
|
}
|
|
void tv_MouseDown(object sender, MouseEventArgs e)
|
|
{
|
|
if (e.Button == MouseButtons.Right)
|
|
{
|
|
TreeNode tn = this.GetNodeAt(new Point(e.X, e.Y));
|
|
if (tn != null)
|
|
{
|
|
this.SelectedNode = tn;
|
|
Application.DoEvents();
|
|
// Display Menu
|
|
ToolStripMenuItem mi = new ToolStripMenuItem();
|
|
ContextMenu cm = new ContextMenu();
|
|
cm.MenuItems.Add("New...",new EventHandler(mi_Click));
|
|
cm.MenuItems.Add("Cut", new EventHandler(mi_Click));
|
|
cm.MenuItems.Add("Copy", new EventHandler(mi_Click));
|
|
cm.MenuItems.Add("Paste", new EventHandler(mi_Click));
|
|
cm.MenuItems.Add("Delete", new EventHandler(mi_Click));
|
|
cm.MenuItems.Add("Properties...", new EventHandler(mi_Click));
|
|
cm.Show(this, new Point(e.X, e.Y));
|
|
}
|
|
}
|
|
}
|
|
|
|
void mi_Click(object sender, EventArgs e)
|
|
{
|
|
MenuItem mi = (MenuItem)sender;
|
|
switch (mi.Text)
|
|
{
|
|
case "New..."://Add a new child node at the current location
|
|
// Should Give the option to the controling code to Add a New Node
|
|
SelectedNode.Expand();
|
|
TreeNode tn = OnNodeNew(this, new vlnTreeEventArgs(SelectedNode));
|
|
if (tn != null)
|
|
{
|
|
SelectedNode.Nodes.Add(tn);
|
|
if (LabelEdit)
|
|
tn.BeginEdit();
|
|
else
|
|
SelectedNode = tn;
|
|
}
|
|
break;
|
|
case "Cut"://Cut the selected node
|
|
// Cut to Clipboard
|
|
break;
|
|
case "Copy"://Copy the selected node
|
|
// Add to Clipboard
|
|
break;
|
|
case "Paste"://Paste the clipboard node
|
|
// this is either a copy or a move depending upon where it came from
|
|
// if it is from a cut then when the paste is done it should be set to a copy
|
|
break;
|
|
case "Delete"://Delete the selected node
|
|
if(OnNodeDelete(this, new vlnTreeEventArgs(SelectedNode)))
|
|
SelectedNode.Remove();
|
|
break;
|
|
case "Properties..."://Show the properties for the selected node
|
|
OnNodeProperties(this,new vlnTreeEventArgs(SelectedNode));
|
|
break;
|
|
default:
|
|
MessageBox.Show(string.Format("Unrecognized Menu Item '{0}'", mi.Text));
|
|
break;
|
|
}
|
|
}
|
|
#endregion
|
|
#region Cursor
|
|
private bool SetupDragCursor(ImageList il, TreeNode tn)
|
|
{
|
|
// Reset image list used for drag image
|
|
il.Images.Clear();
|
|
int howBig = tn.Bounds.Size.Width + this.Indent;
|
|
if (howBig > 256) howBig = 256;
|
|
il.ImageSize = new Size(howBig, tn.Bounds.Height);
|
|
|
|
// Create new bitmap
|
|
// This bitmap will contain the tree node image to be dragged
|
|
Bitmap bmp = new Bitmap(tn.Bounds.Width + this.Indent, tn.Bounds.Height);
|
|
|
|
// Get graphics from bitmap
|
|
Graphics gfx = Graphics.FromImage(bmp);
|
|
|
|
// Draw node icon into the bitmap
|
|
if (this.ImageList != null) gfx.DrawImage(this.ImageList.Images[0], 0, 0);
|
|
|
|
// Draw node label into bitmap
|
|
gfx.DrawString(tn.Text, this.Font, new SolidBrush(this.ForeColor),
|
|
// new SolidBrush(Color.Blue),
|
|
(float)this.Indent, 1.0f);
|
|
|
|
// Add bitmap to imagelist
|
|
_dragImageList.Images.Add(bmp);
|
|
|
|
// Get mouse position in client coordinates
|
|
Point p = this.PointToClient(Control.MousePosition);
|
|
|
|
// Compute delta between mouse position and node bounds
|
|
int dx = p.X + this.Indent - tn.Bounds.Left;
|
|
int dy = p.Y - tn.Bounds.Top;
|
|
|
|
// Begin dragging image
|
|
return DragHelper.ImageList_BeginDrag(_dragImageList.Handle, 0, dx, dy);
|
|
}
|
|
private void tv_ItemDrag(object sender, System.Windows.Forms.ItemDragEventArgs e)
|
|
{
|
|
// Get drag node and select it
|
|
try
|
|
{
|
|
TreeNode dragNode = (TreeNode)e.Item;
|
|
Type t = dragNode.GetType();
|
|
if(_MyLog.IsInfoEnabled)_MyLog.InfoFormat("Item Drag {0} - {1}", t.FullName, t.BaseType.FullName);
|
|
Type t2 = Type.GetType(t.FullName);
|
|
if(t2 != null)
|
|
if(_MyLog.IsInfoEnabled)_MyLog.InfoFormat("Item Drag {0} - {1}", t2.FullName, t2.BaseType.FullName);
|
|
this.SelectedNode = dragNode;
|
|
if (SetupDragCursor(_dragImageList, dragNode))
|
|
{
|
|
this.DoDragDrop(dragNode, DragDropEffects.Move | DragDropEffects.Copy);// Begin dragging
|
|
DragHelper.ImageList_EndDrag();// End dragging image
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
if(_MyLog.IsErrorEnabled)_MyLog.Error("tv_ItemDrag", ex);
|
|
}
|
|
}
|
|
#endregion
|
|
public enum DropPosition : int
|
|
{
|
|
Child = 0, Before = 1, After = 2
|
|
}
|
|
private class DropLocation
|
|
{
|
|
#region Business Methods
|
|
private TreeNode _dropNode;
|
|
public TreeNode DropNode
|
|
{
|
|
get { return _dropNode; }
|
|
set { _dropNode = value; }
|
|
}
|
|
private int _index;
|
|
public int Index
|
|
{
|
|
get { return _index; }
|
|
set { _index = value; }
|
|
}
|
|
private DropPosition _position;
|
|
public DropPosition Position
|
|
{
|
|
get { return _position; }
|
|
set { _position = value; }
|
|
}
|
|
DateTime _lastScroll;
|
|
public DateTime LastScroll
|
|
{
|
|
get { return _lastScroll; }
|
|
}
|
|
private string _location = string.Empty;
|
|
#endregion
|
|
#region Constructors
|
|
public DropLocation(TreeView tv, System.Windows.Forms.DragEventArgs e, DateTime lastScroll)
|
|
{
|
|
_lastScroll = lastScroll;
|
|
_dropNode = tv.GetNodeAt(tv.PointToClient(new Point(e.X, e.Y)));
|
|
if (_dropNode == null) return;
|
|
int OffsetY = tv.PointToClient(Cursor.Position).Y - _dropNode.Bounds.Top;
|
|
if (OffsetY < _dropNode.Bounds.Height / 3) // First Third - Before
|
|
{
|
|
_index = _dropNode.Index;
|
|
_dropNode = _dropNode.Parent;
|
|
_position = DropPosition.Before;
|
|
_location = string.Format("Before1 {0}[{1}] y={2}", _dropNode.Text, _index, OffsetY);
|
|
}
|
|
else if ((OffsetY / 2) < _dropNode.Bounds.Height / 3) // Second Third - Child
|
|
{
|
|
_location = string.Format("Child {0} y={1}", _dropNode.Text, OffsetY);
|
|
_position = DropPosition.Child;
|
|
_index = 0;
|
|
if (_dropNode.Parent == null)
|
|
{
|
|
if(_MyLog.IsInfoEnabled)_MyLog.Info("Root Node");
|
|
}
|
|
}
|
|
else // Last Third - After Now I need to check the X value
|
|
{
|
|
if (_dropNode.NextVisibleNode !=null && _dropNode.Nodes.Count > 0)// Has Children - Insert first child
|
|
{
|
|
// _dropNode = _dropNode.Nodes[0];
|
|
_index = 0;
|
|
_position = DropPosition.Before;
|
|
_location = string.Format("Before2 {0}[{1}] y={2}", _dropNode.Text, _index, OffsetY);
|
|
}
|
|
else // No Children - Insert Next at various levels
|
|
{
|
|
Point pt = tv.PointToClient(new Point(e.X, e.Y));
|
|
TreeNode nextParent = _dropNode.NextNode;
|
|
if (nextParent != null) nextParent = nextParent.Parent;
|
|
do
|
|
{
|
|
_index = _dropNode.Index;
|
|
_dropNode = _dropNode.Parent;
|
|
} while (pt.X < _dropNode.Bounds.X && _dropNode != nextParent);
|
|
_location = string.Format("After {0}[{1}] y={2}", _dropNode.Text, _index, OffsetY);
|
|
_position = DropPosition.After;
|
|
}
|
|
}
|
|
LimitMoves(e);
|
|
}
|
|
public void LimitMoves(DragEventArgs e)
|
|
{
|
|
if ((e.KeyState & 8) == 0)
|
|
{
|
|
//TreeNode dragNode = (TreeNode)e.Data.GetData("System.Windows.Forms.TreeNode");
|
|
//TreeNode dragNode = (TreeNode)e.Data.GetData("TreeTest.FolderTreeNode");
|
|
TreeNode dragNode = vlnTreeView.GetTreeNodeFromData(e.Data);
|
|
switch (_position)
|
|
{
|
|
case DropPosition.Before:
|
|
if (dragNode == _dropNode.Nodes[_index] || dragNode == _dropNode.Nodes[_index].PrevNode)
|
|
{
|
|
// if(_MyLog.IsInfoEnabled)_MyLog.InfoFormat("Before {0} {1} {2} {3} {4}", dragNode.Text ,_position.ToString() , _dropNode.Nodes[_index].Text
|
|
// ,_dropNode.Nodes[_index].PrevNode,_dropNode.Nodes[_index].NextNode);
|
|
_dropNode = null;
|
|
}
|
|
break;
|
|
case DropPosition.Child:
|
|
if (dragNode.Parent == _dropNode)
|
|
{
|
|
// if(_MyLog.IsInfoEnabled)_MyLog.InfoFormat("Child {0} {1} {2} {3} {4} {5}", dragNode.Text ,_position.ToString() , _dropNode.Nodes[_index].Text
|
|
// ,_dropNode.Nodes[_index].PrevNode,_dropNode.Nodes[_index].NextNode,DateTime.Now);
|
|
_dropNode = null;
|
|
}
|
|
break;
|
|
case DropPosition.After:
|
|
if (dragNode == _dropNode.Nodes[_index] || dragNode == _dropNode.Nodes[_index].NextNode)
|
|
{
|
|
// if(_MyLog.IsInfoEnabled)_MyLog.InfoFormat("After {0} {1} {2} {3} {4}", dragNode.Text ,_position.ToString() , _dropNode.Nodes[_index].Text
|
|
// ,_dropNode.Nodes[_index].PrevNode,_dropNode.Nodes[_index].NextNode);
|
|
_dropNode = null;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
public override string ToString()
|
|
{
|
|
return string.Format("{0}[{1}].{2}", _dropNode.Text, _index, _position.ToString());
|
|
}
|
|
#region Drawing
|
|
private void TreeNodeTriangle(Graphics g)
|
|
{
|
|
Rectangle r = _dropNode.Bounds;
|
|
int RightPos = r.Right + 6;
|
|
Point[] RightTriangle = new Point[]{
|
|
new Point(RightPos, r.Y ),
|
|
new Point(RightPos - (r.Height / 2), r.Y + (r.Height / 2)),
|
|
new Point(RightPos, r.Y + r.Height),
|
|
new Point(RightPos - (r.Height / 3), r.Y + (r.Height / 2))
|
|
};
|
|
g.FillPolygon(System.Drawing.Brushes.Black, RightTriangle);
|
|
}
|
|
private void InsertPointer(TreeNode tn, Graphics g)
|
|
{
|
|
TreeView tv = _dropNode.TreeView;
|
|
Rectangle r2 = _dropNode.Nodes[_index].Bounds;
|
|
Rectangle r3 = tn.Bounds;
|
|
int y = (_position == DropPosition.Before ? r2.Y : r3.Bottom);
|
|
int x = r2.Left;
|
|
|
|
if (y == 0)
|
|
{
|
|
return;
|
|
}
|
|
// if(_MyLog.IsInfoEnabled)_MyLog.InfoFormat("Line at {0} Node {1}[{2}] {3}", _location, _dropNode.Text, _index, _position.ToString());
|
|
Color lc = (_position == DropPosition.After ? Color.Red : Color.Blue);
|
|
Brush lb = (_position == DropPosition.After ? Brushes.Red : Brushes.Blue);
|
|
Point[] RightTriangle;
|
|
if (_position == DropPosition.After)
|
|
{
|
|
RightTriangle = new Point[]{
|
|
new Point(x, y ),
|
|
new Point(x+4, y+4),
|
|
new Point(x+8, y)};
|
|
}
|
|
else
|
|
{
|
|
RightTriangle = new Point[]{
|
|
new Point(x, y),
|
|
new Point(x+4, y-4),
|
|
new Point(x+8, y)};
|
|
}
|
|
g.DrawLine(new System.Drawing.Pen(lc, 2), new Point(r2.Left, y), new Point(tv.Width - 8, y));
|
|
g.FillPolygon(lb, RightTriangle);
|
|
}
|
|
public void ShowLocation(System.Windows.Forms.DragEventArgs e, bool ScrollOnly)
|
|
{
|
|
//if (e.Effect == DragDropEffects.None) return;
|
|
if (_dropNode != null)
|
|
{
|
|
// if(_MyLog.IsInfoEnabled)_MyLog.InfoFormat("ShowLocation1 {0} {1}", e.Effect.ToString(), DateTime.Now.Millisecond);
|
|
DragHelper.ImageList_DragShowNolock(false);
|
|
TreeView tv = _dropNode.TreeView;
|
|
TreeNode tmp = tv.GetNodeAt(tv.PointToClient(new Point(e.X, e.Y)));
|
|
// if (!ScrollOnly)
|
|
// {
|
|
if (ScrollTreeView(tmp) || !ScrollOnly)
|
|
{
|
|
if(_MyLog.IsInfoEnabled)_MyLog.InfoFormat("ShowLocation2 {0} {1}", e.Effect.ToString(), DateTime.Now.Millisecond);
|
|
tv.Refresh();
|
|
if (e.Effect != DragDropEffects.None)
|
|
{
|
|
//tv.SelectedNode = dropNode;
|
|
Graphics g = tv.CreateGraphics();
|
|
TreeNodeTriangle(g);
|
|
if (_position != DropPosition.Child)InsertPointer(tmp, g);
|
|
}
|
|
}
|
|
// }
|
|
// else ScrollTreeView(tmp);
|
|
DragHelper.ImageList_DragShowNolock(true);
|
|
}
|
|
}
|
|
#endregion
|
|
public void ShowLocation()
|
|
{
|
|
if(_MyLog.IsInfoEnabled)_MyLog.InfoFormat("{0}[{1}] {2}", _dropNode.Text, _index, _position.ToString());
|
|
}
|
|
#region AutoScroll
|
|
private bool ScrollTreeView(TreeNode tn)
|
|
{
|
|
bool retval = false;
|
|
TimeSpan ts = new TimeSpan(DateTime.Now.Ticks - _lastScroll.Ticks);
|
|
if (ts.Milliseconds > 100)// This controls the scroll speed
|
|
{
|
|
int top = tn.Bounds.Top;
|
|
_lastScroll = DateTime.Now;
|
|
if (tn.TreeView.ClientSize.Height < tn.Bounds.Bottom) tn.EnsureVisible();// Make sure that the current node is visible
|
|
if (tn.NextVisibleNode != null && tn.TreeView.ClientSize.Height < tn.NextVisibleNode.Bounds.Bottom)
|
|
tn.NextVisibleNode.EnsureVisible();// Make sure that the next node is visible
|
|
else
|
|
if (tn.PrevVisibleNode != null && tn.PrevVisibleNode.PrevVisibleNode != null && tn.PrevVisibleNode.PrevVisibleNode.IsVisible == false)
|
|
tn.PrevVisibleNode.PrevVisibleNode.EnsureVisible();// Make sure that the previous node is visible }
|
|
else
|
|
if (tn.PrevVisibleNode != null && tn.PrevVisibleNode.IsVisible == false)
|
|
tn.PrevVisibleNode.EnsureVisible();// Make sure that the previous node is visible
|
|
retval = (top != tn.Bounds.Top);
|
|
// if (retval) if(_MyLog.IsInfoEnabled)_MyLog.Info("Scroll");
|
|
}
|
|
return retval;
|
|
}
|
|
#endregion
|
|
public bool Equals(DropLocation dl)
|
|
{
|
|
return (dl != null && _lastScroll.Equals(dl.LastScroll) && _dropNode.Equals(dl.DropNode) &&
|
|
_position.Equals(dl.Position));
|
|
}
|
|
}
|
|
private DropLocation _LastDropLocation = null;
|
|
private void tv_DragOver(object sender, System.Windows.Forms.DragEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
TreeNode dragNode = GetTreeNodeFromData(e.Data);
|
|
// Compute drag position and move image
|
|
Point formP = this.FindForm().PointToClient(new Point(e.X, e.Y));
|
|
DragHelper.ImageList_DragMove(formP.X - this.Left, formP.Y - this.Top);
|
|
DropLocation dl = new DropLocation(this, e, _LastDropLocation == null ? DateTime.Now : _LastDropLocation.LastScroll);
|
|
string s = string.Empty;
|
|
if (dl.DropNode == null)
|
|
{
|
|
e.Effect = DragDropEffects.None;
|
|
}
|
|
else
|
|
{
|
|
DragDropEffects ee = e.Effect;
|
|
if ((e.KeyState & 8) == 8)
|
|
ee = DragDropEffects.Copy; // Copy it
|
|
else
|
|
ee = DragDropEffects.Move; // Move it
|
|
if (IsChild(dragNode, dl.DropNode))
|
|
ee = DragDropEffects.None; // Don't copy or move to a child node
|
|
if (e.Effect != ee) e.Effect = ee;
|
|
dl.ShowLocation(e, dl.Equals(_LastDropLocation));
|
|
_LastDropLocation = dl;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
if(_MyLog.IsErrorEnabled)_MyLog.Error("tv_DragOver", ex);
|
|
}
|
|
}
|
|
private static TreeNode GetTreeNodeFromData(IDataObject datobj)
|
|
{
|
|
foreach (string s in datobj.GetFormats())
|
|
{
|
|
try
|
|
{
|
|
return (TreeNode)datobj.GetData(s);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
if(_MyLog.IsErrorEnabled)_MyLog.Error("GetTreeNodeFromData", ex);
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
private void tv_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
TreeNode dragNode = GetTreeNodeFromData(e.Data);
|
|
DragHelper.ImageList_DragLeave(this.Handle);
|
|
int index = _LastDropLocation.Index + (_LastDropLocation.Position == DropPosition.After ? 1 : 0);
|
|
if (dragNode.Parent == _LastDropLocation.DropNode && dragNode.Index <= _LastDropLocation.Index) index--;
|
|
if (e.Effect == DragDropEffects.Move)// If Move Remove drag node from parent
|
|
dragNode.Remove();
|
|
else
|
|
dragNode = Clone(dragNode);
|
|
_LastDropLocation.DropNode.Nodes.Insert(index, dragNode);
|
|
this.SelectedNode = dragNode;
|
|
OnNodeDragDrop(sender, new vlnTreeEventArgs(dragNode, _LastDropLocation.DropNode,index));
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
if(_MyLog.IsErrorEnabled)_MyLog.Error("tv_DragDrop", ex);
|
|
}
|
|
}
|
|
private void DumpMembers(object o)
|
|
{
|
|
Type t = o.GetType();
|
|
if(_MyLog.IsInfoEnabled)_MyLog.InfoFormat("\r\n\r\nMembers for type {0}", t.ToString());
|
|
MemberInfo[] mis = t.GetMembers();
|
|
int i = 0;
|
|
foreach (MemberInfo mi in mis)
|
|
{
|
|
i++;
|
|
try
|
|
{
|
|
if(mi.MemberType != MemberTypes.Method)
|
|
if(_MyLog.IsInfoEnabled)_MyLog.InfoFormat("{0} {1} {2}", i, mi.Name, mi.MemberType);
|
|
// if (fi.Name == "TreeView")
|
|
// fi.SetValue(o, null);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
if(_MyLog.IsErrorEnabled)_MyLog.Error("DumpMembers", ex);
|
|
}
|
|
}
|
|
}
|
|
private TreeNode Clone(TreeNode tn)
|
|
{
|
|
|
|
TreeNode tmp = (TreeNode)tn.Clone();
|
|
ExpandMatch(tmp,tn);
|
|
return tmp;
|
|
}
|
|
private void tv_DragDropOld(object sender, System.Windows.Forms.DragEventArgs e)
|
|
{
|
|
TreeNode dragNode = (TreeNode)e.Data.GetData("System.Windows.Forms.TreeNode");// Get the drag node
|
|
DragHelper.ImageList_DragLeave(this.Handle);
|
|
TreeNode cloneNode = (TreeNode)dragNode.Clone();// copy the source node
|
|
ExpandMatch(cloneNode, dragNode);
|
|
_LastDropLocation.DropNode.Nodes.Insert(_LastDropLocation.Index + (_LastDropLocation.Position == DropPosition.After ? 1 : 0), cloneNode);
|
|
if (e.Effect == DragDropEffects.Move)// If Move Remove drag node from parent
|
|
dragNode.Remove();
|
|
this.SelectedNode = cloneNode;
|
|
}
|
|
private void tv_DragEnter(object sender, System.Windows.Forms.DragEventArgs e)
|
|
{
|
|
DragHelper.ImageList_DragEnter(this.Handle, e.X - this.Left, e.Y - this.Top);
|
|
}
|
|
private void tv_DragLeave(object sender, System.EventArgs e)
|
|
{
|
|
DragHelper.ImageList_DragLeave(this.Handle);
|
|
this.Refresh();
|
|
}
|
|
private void ExpandMatch(TreeNode tn1, TreeNode tn2)
|
|
{
|
|
if (tn2.IsExpanded) tn1.Expand();
|
|
foreach (TreeNode tc in tn2.Nodes) ExpandMatch(tn1.Nodes[tc.Index], tc);
|
|
}
|
|
private bool IsChild(TreeNode parent, TreeNode child)
|
|
{
|
|
if (parent.Equals(child)) return true;// Check against self
|
|
foreach (TreeNode tc in parent.Nodes) if (IsChild(tc, child)) return true;//Check all children
|
|
return false;// Must not be a child at this level
|
|
}
|
|
}
|
|
public class DragHelper
|
|
{
|
|
[DllImport("comctl32.dll")]
|
|
public static extern bool InitCommonControls();
|
|
|
|
[DllImport("comctl32.dll", CharSet = CharSet.Auto)]
|
|
public static extern bool ImageList_BeginDrag(IntPtr himlTrack, int
|
|
iTrack, int dxHotspot, int dyHotspot);
|
|
|
|
[DllImport("comctl32.dll", CharSet = CharSet.Auto)]
|
|
public static extern bool ImageList_DragMove(int x, int y);
|
|
|
|
[DllImport("comctl32.dll", CharSet = CharSet.Auto)]
|
|
public static extern void ImageList_EndDrag();
|
|
|
|
[DllImport("comctl32.dll", CharSet = CharSet.Auto)]
|
|
public static extern bool ImageList_DragEnter(IntPtr hwndLock, int x, int y);
|
|
|
|
[DllImport("comctl32.dll", CharSet = CharSet.Auto)]
|
|
public static extern bool ImageList_DragLeave(IntPtr hwndLock);
|
|
|
|
[DllImport("comctl32.dll", CharSet = CharSet.Auto)]
|
|
public static extern bool ImageList_DragShowNolock(bool fShow);
|
|
static DragHelper()
|
|
{
|
|
InitCommonControls();
|
|
}
|
|
}
|
|
}
|