I had google'd this pretty good.  Figured out my own solution.  Wrote
it up for others to check out.

It's at http://www.urona.com/drag.htm.

The good stuff is as follows:

struct rDrag {
    internal bool Gone; // user dragged OFF the appropriate drop-
control
    internal bool On;   // we're dragging
    internal int Index; }
rDrag mDragIt;  // don't forget to set .AllowDrop on the ListView

...

private void It_MouseDown(object sender, MouseEventArgs e) {
    if ((mDragIt.Gone) || (mDragIt.Index < 0)) try {
        ListViewItem Item = It.HitTest(e.X, e.Y).Item;  // on
MouseDown, X,Y is relative
        if (Item != null) { mDragIt.Index = Item.Index; mDragIt.Gone =
false; mDragIt.On = false; }  // .On only if .MouseMove
    } catch (ArgumentOutOfRangeException ex) { }  // for .HitTest
}

private void It_MouseMove(object sender, MouseEventArgs e) {
    if ((!mDragIt.On) && (mDragIt.Index >= 0)) { mDragIt.On = true;
It.DoDragDrop(mDragIt.Index, DragDropEffects.Move); }
}  // because MouseDown sets mDragIt.Index, and MouseMove
initiates .DoDragDrop, the data passed is ignored as follows

private void It_DragOver(object sender, DragEventArgs e) {
    if (mDragIt.Index >= 0) try {
        ListViewItem Item = It.HitTest(It.PointToClient(new Point(e.X,
e.Y))).Item;  // X,Y is absolute
        if ((Item != null) && (Item.Index != mDragIt.Index) &&
(Item.Index != (mDragIt.Index + 1))) {
            e.Effect = DragDropEffects.Move;
        } else { e.Effect = DragDropEffects.None; }
    } catch (ArgumentOutOfRangeException ex) { e.Effect =
DragDropEffects.None; }  // for .HitTest
}

private void It_DragDrop(object sender, DragEventArgs e) {
    if (mDragIt.Index >= 0) try {
        ListViewItem Item = It.HitTest(lvRoute.PointToClient(new Point
(e.X, e.Y))).Item;  // X,Y is absolute
        if ((Item != null) && (Item.Index != mDragIt.Index) &&
(Item.Index != (mDragIt.Index + 1))) {
            // however you wanna handle this ... mDragIt.Index is what
was dragged ... Item.Index is the drop
        }
    } finally { mDragIt.Index = -1; mDragIt.On = false; }
}

private void lvRoute_DragLeave(object sender, EventArgs e) {
    mDragIt.Gone = true;  // bad user ... off the reservation
}  // this is important ... it allows us to start a new drag-drop
despite the fact mDragIt.Index >= 0

private void lvRoute_DragEnter(object sender, DragEventArgs e) {
    mDragRoute.Gone = false;  // ah good ... they came back
}

Reply via email to