TreeView 中的 HotTracking 不适用于拖放

发布于 2024-12-04 19:03:52 字数 149 浏览 0 评论 0原文

我有一个简单的 TreeView,其 HotTracking 属性设置为 True。当我将鼠标移到某个项目上时它会起作用。但当我使用拖放并将某些内容拖到 TreeView 项上时,它不起作用。有没有办法将 HotTracking 与 DragDrop 结合使用?或者有什么解决方法吗?

I have a simple TreeView with HotTracking Property set to True. It works when I move the mouse over an item. But it doesn't work when I use Drag&Drop and Drag something over a TreeView Item. Is there a way to use the HotTracking with DragDrop? Or any workarounds?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

空名 2024-12-11 19:03:52

根据设计,该控件仅获取 D+D 通知,而不获取鼠标消息。您可以简单地自己选择节点:

    private void treeView1_DragOver(object sender, DragEventArgs e) {
        if (e.Data.GetDataPresent("something")) {
            var pos = treeView1.PointToClient(new Point(e.X, e.Y));
            var hit = treeView1.HitTest(pos);
            if (hit.Location == TreeViewHitTestLocations.Label) {
                treeView1.SelectedNode = hit.Node;
                e.Effect = DragDropEffects.Copy;
            }
            else e.Effect = DragDropEffects.None;
        }
    }

您通常需要做更多工作才能让用户滚动视图并展开节点。

By design, the control only gets D+D notifications, no mouse messages. You could simply select the node yourself:

    private void treeView1_DragOver(object sender, DragEventArgs e) {
        if (e.Data.GetDataPresent("something")) {
            var pos = treeView1.PointToClient(new Point(e.X, e.Y));
            var hit = treeView1.HitTest(pos);
            if (hit.Location == TreeViewHitTestLocations.Label) {
                treeView1.SelectedNode = hit.Node;
                e.Effect = DragDropEffects.Copy;
            }
            else e.Effect = DragDropEffects.None;
        }
    }

You typically need to do more work to let the user scroll the view and expand nodes.

黑凤梨 2024-12-11 19:03:52

按照 @Hans 建议选择节点是一个简单的解决方案,但如果节点选择上存在一些事件,或者您只需要保留选定的节点,则可能无法使用。
我发现的唯一方法是使用 VisualStylesRenderer custumDraw 节点。

private void plTree_DragOver(object sender, DragEventArgs e)
    {            
        Point pt = plTree.PointToClient(new Point(e.X, e.Y));

        var overNode = plTree.GetNodeAt(pt);
        bool canMoveTo = overNode != null && 
                         TreeNodeIsFolder(overNode) && 
                         !IsFirstNodeParentToSecond(GetDraggedNodes(e)[0], overNode);// all dragged nodes are of the same parent
        e.Effect = canMoveTo ? DragDropEffects.Move : DragDropEffects.None;

        if (overNode == null) return;

        if (_lastCustomDrawNode != overNode)
        {
            NormalDrawNode(_lastCustomDrawNode);
            CustomDrawNode(overNode);
        }
        _lastCustomDrawNode = overNode;
    }

    private void NormalDrawNode(TreeNode aNode)
    {
        if (aNode == null) return;

        if (_normalNodeRenderer == null)
            _normalNodeRenderer = new VisualStyleRenderer("Explorer::TreeView", 1, 1);
        Debug.WriteLine("normal render" + DateTime.Now);
        RenderTreeNode(_normalNodeRenderer, aNode, true);

        _lastCustomDrawNode = null;
    }

    private void CustomDrawNode(TreeNode aNode)
    {
        if (_hotNodeRenderer == null)
            _hotNodeRenderer = new VisualStyleRenderer("Explorer::TreeView", 1, 2);
        Debug.WriteLine("custom render" + DateTime.Now);
        RenderTreeNode(_hotNodeRenderer, aNode, false);
    }

    private void RenderTreeNode(VisualStyleRenderer renderer, TreeNode aNode, bool drawDefaultBck)
    {
        if(_treeGraphics == null)
             _treeGraphics = plTree.CreateGraphics();

        const int iconShift = 21;
        Rectangle aRec = aNode.Bounds;

        var bckRec = new Rectangle(aRec.Location.X - iconShift, aRec.Location.Y, aRec.Width + iconShift, aRec.Height);

        if (!drawDefaultBck)
            renderer.DrawBackground(_treeGraphics, bckRec);
        else
            _treeGraphics.FillRectangle(_treebckgBrush, bckRec);

        var textRec = new Rectangle(aRec.Location.X + 1, aRec.Location.Y - 1, aRec.Width, aRec.Height);
        TextRenderer.DrawText(_treeGraphics, aNode.Text, GetTreeNodeFont(aNode), textRec, Color.FromKnownColor(KnownColor.ControlText));

        var imgRec = new Rectangle(aRec.Location.X + 2 - iconShift, aRec.Location.Y, 16, 16);
        renderer.DrawImage(_treeGraphics, imgRec, ImageListTree.Images[aNode.ImageIndex]);
    }

这篇文章对主题绘制有很大帮助:
VisualStyleRenderer 和主题 (WinForms)

Selecting a Node as @Hans suggested is a simple solution but can be unusable if there is some events on node selection, or if you just need keeping the selected node.
The only way I found is custumDraw the node using VisualStylesRenderer.

private void plTree_DragOver(object sender, DragEventArgs e)
    {            
        Point pt = plTree.PointToClient(new Point(e.X, e.Y));

        var overNode = plTree.GetNodeAt(pt);
        bool canMoveTo = overNode != null && 
                         TreeNodeIsFolder(overNode) && 
                         !IsFirstNodeParentToSecond(GetDraggedNodes(e)[0], overNode);// all dragged nodes are of the same parent
        e.Effect = canMoveTo ? DragDropEffects.Move : DragDropEffects.None;

        if (overNode == null) return;

        if (_lastCustomDrawNode != overNode)
        {
            NormalDrawNode(_lastCustomDrawNode);
            CustomDrawNode(overNode);
        }
        _lastCustomDrawNode = overNode;
    }

    private void NormalDrawNode(TreeNode aNode)
    {
        if (aNode == null) return;

        if (_normalNodeRenderer == null)
            _normalNodeRenderer = new VisualStyleRenderer("Explorer::TreeView", 1, 1);
        Debug.WriteLine("normal render" + DateTime.Now);
        RenderTreeNode(_normalNodeRenderer, aNode, true);

        _lastCustomDrawNode = null;
    }

    private void CustomDrawNode(TreeNode aNode)
    {
        if (_hotNodeRenderer == null)
            _hotNodeRenderer = new VisualStyleRenderer("Explorer::TreeView", 1, 2);
        Debug.WriteLine("custom render" + DateTime.Now);
        RenderTreeNode(_hotNodeRenderer, aNode, false);
    }

    private void RenderTreeNode(VisualStyleRenderer renderer, TreeNode aNode, bool drawDefaultBck)
    {
        if(_treeGraphics == null)
             _treeGraphics = plTree.CreateGraphics();

        const int iconShift = 21;
        Rectangle aRec = aNode.Bounds;

        var bckRec = new Rectangle(aRec.Location.X - iconShift, aRec.Location.Y, aRec.Width + iconShift, aRec.Height);

        if (!drawDefaultBck)
            renderer.DrawBackground(_treeGraphics, bckRec);
        else
            _treeGraphics.FillRectangle(_treebckgBrush, bckRec);

        var textRec = new Rectangle(aRec.Location.X + 1, aRec.Location.Y - 1, aRec.Width, aRec.Height);
        TextRenderer.DrawText(_treeGraphics, aNode.Text, GetTreeNodeFont(aNode), textRec, Color.FromKnownColor(KnownColor.ControlText));

        var imgRec = new Rectangle(aRec.Location.X + 2 - iconShift, aRec.Location.Y, 16, 16);
        renderer.DrawImage(_treeGraphics, imgRec, ImageListTree.Images[aNode.ImageIndex]);
    }

this post helps a lot with theme drawing:
VisualStyleRenderer and themes (WinForms)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文