protected override void OnDragOver(DragEventArgs e)
{
// determine the node under the cursor
Point cursor = _treeCtrl.PointToClient(new Point(e.X, e.Y));
BindingTreeNode node = (BindingTreeNode)_treeCtrl.GetNodeAt(cursor);
// determine what effect the user is trying to accomplish
DragDropEffects desiredEffect = GetDragDropDesiredEffect(e);
// determine if the user is trying to drag to the top, middle or bottom areas of the node
DragDropPosition position = DragDropPosition.Default;
if (this.AllowDropToIndex && node != null)
{
float result = 1f*(cursor.Y - node.Bounds.Y)/node.Bounds.Height;
if (result <= 0.2f)
position = DragDropPosition.Before;
else if (result >= 0.8f)
position = DragDropPosition.After;
}
// optimization: only care if different than the last known drop-target node, or different desired effect, or different drop position
if (node != _dropTargetNode || desiredEffect != _dropEffect || position != _dropPosition)
{
_treeCtrl.BeginUpdate(); // suspend drawing
// un-highlight the last known drop-target node
HighlightNode(_dropTargetNode, false);
SetInsertMark(_dropTargetNode, DragDropPosition.Default);
// set the drop target node to this node
_dropTargetNode = node;
_dropEffect = desiredEffect;
_dropPosition = position;
// check if drop target node exists and what kind of operation it will accept
DragDropKind acceptableKind = (_dropTargetNode == null) ?
DragDropKind.None : _dropTargetNode.CanAcceptDrop(GetDragDropData(e), GetDragDropKind(desiredEffect), _dropPosition);
// display the appropriate effect cue based on the result
e.Effect = GetDragDropEffect(acceptableKind);
// if the drop target is valid and willing to accept data, highlight it
if (acceptableKind != DragDropKind.None)
{
HighlightNode(_dropTargetNode, _dropPosition == DragDropPosition.Default);
SetInsertMark(_dropTargetNode, _dropPosition);
}
_treeCtrl.EndUpdate(); // resume drawing
}
// perform drag scrolling
if (_treeCtrl.ClientRectangle.Contains(cursor))
{
if (cursor.Y > _treeCtrl.Height - _treeCtrl.ItemHeight/2)
SendMessage(_treeCtrl.Handle, (int) WindowsMessages.WM_VSCROLL, new IntPtr(1), IntPtr.Zero);
else if (cursor.Y < _treeCtrl.ItemHeight/2)
SendMessage(_treeCtrl.Handle, (int) WindowsMessages.WM_VSCROLL, IntPtr.Zero, IntPtr.Zero);
}
base.OnDragOver(e);
}