2

Okay so in my DragDropManager I have set:

DragDropEffects.Scroll

as an allowed effect but for some reason it's not working properly. It still is not scrolling at all when I am trying to scroll. Could someone please explain to me properly about this.

I am trying to use this while dragging my categories around.

I have checked the MSDN but it is really uninformative on what the feature actually does and how to use it.

I am sorry if this question is silly but I hope someone can help me out.

Hello World
  • 1,379
  • 4
  • 20
  • 41
  • 2
    It is an *extra* flag, you always use it in combination with another like Move or Copy. You use it tell the D+D plumbing that you are scrolling the target *yourself*. So that it knows to generate more DragOver events, more than just the ones generated from a mouse move. – Hans Passant May 23 '12 at 18:28
  • Would I simply need to monitor the position of the LeftMouse when dragging, assuming I would say set it to 5-10 pixels away? Would I want it to loop so it checks it constantly? – Hello World May 24 '12 at 08:04
  • Get an answer by explaining what problem you are trying to solve, it is entirely unclear. – Hans Passant May 24 '12 at 10:38

2 Answers2

1

Two solutions can be found here. One is using SendMessage, the other is pure .NET code.
http://www.dotnet247.com/247reference/msgs/16/81341.aspx
(the site seems to be down, archived page can be found here)

Related windows message codes are described here:
ListView onScroll event

My resulting code is below. It is incomplete though in that aspect that I would like it to have ability to detect the existence of vertical and horizontal scrollbars and adjust the bottom and right scroll-trigger areas accordingly.

private void treeView_DragOver(object sender, DragEventArgs e)
{
    TreeView senderTree = sender as TreeView;

    TreeNode destinationNode;
    TreeNode newNode = GetDragTreeNode(out destinationNode, sender, e);

    if (newNode == null)
    {
        e.Effect = DragDropEffects.None;
        return;
    }

    int scrollDetectRangeU = 10;
    int scrollDetectRangeL = 10;
    int scrollDetectRangeB = 10 + 20;
    int scrollDetectRangeR = 10 + 20;
    Point treeCoord = CoordToTreeCoord(senderTree, e);

    if (treeCoord.Y < scrollDetectRangeU 
        && (destinationNode == null || destinationNode.PrevVisibleNode != null))
    {
        SendMessage(senderTree.Handle, WindowsMessages.WM_VSCROLL, ScrollBarCommands.SB_LINEUP, IntPtr.Zero);    //scroll up
        Thread.Sleep(10);   //slow down the scrolling a bit
    }
    else if (treeCoord.Y >= senderTree.Height - scrollDetectRangeB 
        && (destinationNode == null || destinationNode.NextVisibleNode != null))
    {
        SendMessage(senderTree.Handle, WindowsMessages.WM_VSCROLL, ScrollBarCommands.SB_LINEDOWN, IntPtr.Zero);    //scroll down
        Thread.Sleep(10);   //slow down the scrolling a bit
    }

    if (treeCoord.X < scrollDetectRangeL)
    {
        SendMessage(senderTree.Handle, WindowsMessages.WM_HSCROLL, ScrollBarCommands.SB_LINELEFT, IntPtr.Zero);     //scroll left
    }
    else if (treeCoord.X >= senderTree.Width - scrollDetectRangeR)
    {
        SendMessage(senderTree.Handle, WindowsMessages.WM_HSCROLL, ScrollBarCommands.SB_LINERIGHT, IntPtr.Zero);     //scroll right
    }

}

private static TreeNode GetDragTreeNode(out TreeNode destinationNode, object sender, DragEventArgs e)
{
    TreeNode newNode = null;

    if (e.Data.GetDataPresent("System.Windows.Forms.TreeNode", false))  
    {
        newNode = (TreeNode)e.Data.GetData("System.Windows.Forms.TreeNode");
    }

    if (newNode != null)
    {
        destinationNode = CoordToTreeNode(sender, e);    
    }
    else
    {
        destinationNode = null;
    }

    return newNode;
}

public static Point CoordToTreeCoord(object senderTree, DragEventArgs e)
{
    return CoordToTreeCoord(senderTree as TreeView, e.X, e.Y, true);
}

public static Point CoordToTreeCoord(TreeView senderTree, int x, int y, bool usePointToClient)
{
    Point pt = usePointToClient ? senderTree.PointToClient(new Point(x, y)) : new Point(x, y);

    return pt;
}

public static TreeNode CoordToTreeNode(object senderTree, DragEventArgs e)
{
    return CoordToTreeNode(senderTree as TreeView, e.X, e.Y, true);
}

public static TreeNode CoordToTreeNode(TreeView senderTree, int x, int y, bool usePointToClient)
{
    Point pt = CoordToTreeCoord(senderTree, x, y, usePointToClient);
    TreeNode destinationNode = senderTree.GetNodeAt(pt);

    return destinationNode;
}

[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, Int32 Msg, ScrollBarCommands wParam, IntPtr lParam);  

public enum ScrollBarCommands : int
{
    SB_LINEUP = 0,
    SB_LINELEFT = 0,
    SB_LINEDOWN = 1,
    SB_LINERIGHT = 1,
    SB_PAGEUP = 2,
    SB_PAGELEFT = 2,
    SB_PAGEDOWN = 3,
    SB_PAGERIGHT = 3,
    SB_THUMBPOSITION = 4,
    SB_THUMBTRACK = 5,
    SB_TOP = 6,
    SB_LEFT = 6,
    SB_BOTTOM = 7,
    SB_RIGHT = 7,
    SB_ENDSCROLL = 8
}

public static class WindowsMessages
{
    // Windows messages 
    public const int WM_PAINT = 0x000F;
    public const int WM_HSCROLL = 0x0114;
    public const int WM_VSCROLL = 0x0115;
    public const int WM_MOUSEWHEEL = 0x020A;
    public const int WM_KEYDOWN = 0x0100;
    public const int WM_LBUTTONUP = 0x0202;

    // ScrollBar types 
    public const int SB_HORZ = 0;
    public const int SB_VERT = 1;

    // ScrollBar interfaces 
    public const int SIF_TRACKPOS = 0x10;
    public const int SIF_RANGE = 0x01;
    public const int SIF_POS = 0x04;
    public const int SIF_PAGE = 0x02;
    public const int SIF_ALL = SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS;

    // ListView messages 
    public const uint LVM_SCROLL = 0x1014;
    public const int LVM_FIRST = 0x1000;
    public const int LVM_SETGROUPINFO = (LVM_FIRST + 147);

}
Community
  • 1
  • 1
Roland Pihlakas
  • 4,246
  • 2
  • 43
  • 64
0

As the link in the accepted answer seems broken (again?) I wondered if anyone browsing this issue might be interested in a blog covering Drag & Drop which has some demo code managing scrolling while dragging linked on GitHub.

mikeoncode.blogspot.co.uk

One aspect is that the XY co-ordinates provided by the drag event arguments are screen based and (if you are going to use those) you need to compute (and track) the position of the scrollable region using those co-ordinates. Once that is established it is simply a matter of measuring the relative position of the drag cursor and initiating a change to the scroll bar as the cursor nears a relevant boundary. Source code on GitHub

Mike
  • 391
  • 4
  • 11