Explanation of DragDropEffects.Scroll

本文关键字:Scroll DragDropEffects of Explanation | 更新日期: 2023-09-27 18:35:02

好的,所以我在我的DragDropManager中设置了:

DragDropEffects.Scroll

作为允许的效果,但由于某种原因它无法正常工作。当我尝试滚动时,它仍然根本没有滚动。有人可以适当地向我解释一下吗?

我正在尝试使用它,同时拖动我的类别。

我已经检查了MSDN,但它实际上没有关于该功能实际做什么以及如何使用它的信息。

如果这个问题很愚蠢,我很抱歉,但我希望有人可以帮助我。

Explanation of DragDropEffects.Scroll

可以在这里找到两种解决方案。一种是使用SendMessage,另一种是纯.NET代码。
http://www.dotnet247.com/247reference/msgs/16/81341.aspx
(该网站似乎已关闭,存档页面可以在这里找到(

相关窗口消息代码如下所述:
列表视图滚动事件

我生成的代码如下。尽管在这方面,我希望它能够检测垂直和水平滚动条的存在并相应地调整底部和右侧滚动触发区域,但这是不完整的。

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);
}

因为接受答案中的链接似乎已损坏(再次?我想知道是否有任何浏览此问题的人可能对涵盖拖放的博客感兴趣,该博客有一些演示代码,在 GitHub 上拖动链接时管理滚动。

mikeoncode.blogspot.co.uk

一方面,拖动事件参数提供的 XY 坐标是基于屏幕的,并且(如果要使用这些坐标(您需要使用这些坐标计算(和跟踪(可滚动区域的位置。一旦建立起来,只需测量拖动光标的相对位置,并在光标接近相关边界时启动对滚动条的更改。GitHub 上的源代码