好的,所以在我的 DragDropManager 中我设置了:
DragDropEffects.Scroll
作为一种允许的效果,但由于某种原因它不能正常工作。当我尝试滚动时,它仍然根本不滚动。有人可以正确地向我解释这一点。
我试图在拖动我的类别时使用它。
我已经检查了 MSDN,但对于该功能的实际作用以及如何使用它确实没有提供任何信息。
如果这个问题很愚蠢,我很抱歉,但我希望有人能帮助我。
好的,所以在我的 DragDropManager 中我设置了:
DragDropEffects.Scroll
作为一种允许的效果,但由于某种原因它不能正常工作。当我尝试滚动时,它仍然根本不滚动。有人可以正确地向我解释这一点。
我试图在拖动我的类别时使用它。
我已经检查了 MSDN,但对于该功能的实际作用以及如何使用它确实没有提供任何信息。
如果这个问题很愚蠢,我很抱歉,但我希望有人能帮助我。
在这里可以找到两种解决方案。一种是使用SendMessage
.NET 代码,另一种是纯 .NET 代码。
http://www.dotnet247.com/247reference/msgs/16/81341.aspx
(该网站似乎已关闭,存档页面可以在这里找到)
相关的windows消息代码描述在这里:
ListView onScroll event
我的结果代码如下。虽然在这方面我希望它能够检测垂直和水平滚动条的存在并相应地调整底部和右侧滚动触发区域,但它是不完整的。
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);
}
由于已接受答案中的链接似乎已损坏(再次?)我想知道是否有人浏览此问题可能会对涵盖 Drag & Drop 的博客感兴趣,该博客有一些演示代码管理在 GitHub 上拖动链接时的滚动。
一方面是拖动事件参数提供的 XY 坐标是基于屏幕的,并且(如果您要使用它们)您需要使用这些坐标计算(和跟踪)可滚动区域的位置。一旦确定,只需测量拖动光标的相对位置并在光标接近相关边界时启动滚动条的更改。GitHub上的源代码