【问题标题】:Correct Rendering of Overridden TreeView正确渲染覆盖的 TreeView
【发布时间】:2012-01-09 11:43:20
【问题描述】:

我在使用标准 Windows 窗体 TreeView 时遇到了问题;特别是当树视图没有焦点时,默认控件用于呈现选定节点的颜色。这是一种浅灰色,在某些屏幕上几乎看不见。随后,我对 TreeView 进行了子类化并覆盖了 TreeView OnDrawNode 事件,以按照我的意愿为我的节点着色。这运行良好,但现在我的自定义OnDrawNode 事件覆盖了“HotTracking”(当鼠标悬停在给定树节点上时主动突出显示)。我对Graphics 类不太熟悉,想知道如何修改我当前的子类以包含热跟踪?我知道我可以使用e.Graphics.DrawLine(Pen pen, Point p1, Point p2);,但这会变得很乱,有没有更简单的方法?

这是现有的代码:

class CustomTreeView : TreeView 
{
    public CustomTreeView() 
    {
        this.DrawMode = TreeViewDrawMode.OwnerDrawText;
    }

    // Override the drawMode of TreeView.
    protected override void OnDrawNode(DrawTreeNodeEventArgs e) 
    {
        TreeNodeStates treeState = e.State;
        Font treeFont = e.Node.NodeFont ?? e.Node.TreeView.Font;

        // Colors.
        Color foreColor = e.Node.ForeColor;
        string strDeselectedColor = @"#6B6E77", strSelectedColor = @"#94C7FC"; //@"#1ABEE8"; //@"#2FC0EE"; //@"#3A8FEA";
        Color selectedColor = System.Drawing.ColorTranslator.FromHtml(strSelectedColor);
        Color deselectedColor = System.Drawing.ColorTranslator.FromHtml(strDeselectedColor);

        // New brush.
        SolidBrush selectedTreeBrush = new SolidBrush(selectedColor);
        SolidBrush deselectedTreeBrush = new SolidBrush(deselectedColor);

        // Set default font color.
        if (foreColor == Color.Empty)
            foreColor = e.Node.TreeView.ForeColor;

        // Draw bounding box and fill.
        if (e.Node == e.Node.TreeView.SelectedNode) 
        {
            // Use appropriate brush depending on if the tree has focus.
            if (this.Focused)
            {
                foreColor = SystemColors.HighlightText;
                e.Graphics.FillRectangle(selectedTreeBrush /*SystemBrushes.Highlight*/, e.Bounds);
                ControlPaint.DrawFocusRectangle(e.Graphics, e.Bounds, foreColor, SystemColors.Highlight);
                TextRenderer.DrawText(e.Graphics, e.Node.Text, treeFont, e.Bounds, foreColor, TextFormatFlags.GlyphOverhangPadding);
            }
            else
            {
                foreColor = SystemColors.HighlightText;
                e.Graphics.FillRectangle(deselectedTreeBrush /*SystemBrushes.Highlight*/, e.Bounds);
                ControlPaint.DrawFocusRectangle(e.Graphics, e.Bounds, foreColor, SystemColors.Highlight);
                TextRenderer.DrawText(e.Graphics, e.Node.Text, treeFont, e.Bounds, foreColor, TextFormatFlags.GlyphOverhangPadding);
            }
        }
        else 
        {
            // This is firing but is being over written, perhaps by the above?
            if ((e.State & TreeNodeStates.Hot) == TreeNodeStates.Hot)
            {
                e.DrawDefault = true;
                e.Graphics.FillRectangle(SystemBrushes.Window, e.Bounds);
                TextRenderer.DrawText(e.Graphics, e.Node.Text, treeFont, e.Bounds, System.Drawing.Color.Blue, TextFormatFlags.GlyphOverhangPadding);
            }
            else
            {
                e.Graphics.FillRectangle(SystemBrushes.Window, e.Bounds);
                TextRenderer.DrawText(e.Graphics, e.Node.Text, treeFont, e.Bounds, foreColor, TextFormatFlags.GlyphOverhangPadding);
           }   
        }
    }

一如既往,非常感谢您抽出宝贵时间。

【问题讨论】:

  • “这是一种浅灰色,在某些屏幕上几乎看不见。” 所以那个人的电脑基本上不能用了,对吧?因为 Windows 在整个系统和所有其他应用程序中使用相同的非活动突出显示颜色。我希望这是一台只运行您的应用程序的信息亭机器,否则更改它是徒劳的。而且我无论如何都不建议更改它,因为正如您所观察到的,所有者绘图会使一切变得更加困难。在这种情况下,您需要将代码添加到鼠标事件处理程序方法中以自己进行热跟踪。它不会是自动的。
  • 为什么改变它是“徒劳的”?在白色背景上,这种不活动的高亮颜色是非常淡的灰色,在某些情况下不容易看到(就像我为上面的 treeView 概述的问题)。处理“HotTracking”的鼠标事件处理程序(MouseMove 或一些此类事件)可能会调用OnDrawNode 事件来呈现节点 - 问题仍然存在。如何最好地重新实现“HotTracking”功能。感谢您的宝贵时间...

标签: c# winforms inheritance treeview overriding


【解决方案1】:

您需要注意代码中的 e.State。 DrawTreeNodeEventArgs.State 属性告诉您节​​点发生了什么,相应地选择颜色。另请查看 TreeNode.DrawNode 文档中显示的 MSDN 库示例以获取指导。

【讨论】:

  • 非常感谢您抽出时间汉斯。
  • 汉斯,我现在正在检查选定的节点。如果未选择它,我会检查鼠标是否在节点上 usng if ((e.State & TreeNodeStates.Hot) == TreeNodeStates.Hot) 然后我尝试以不同的方式绘制文本。它正在点击此代码,但似乎没有渲染它。你能给我其他的建议吗?我已经修改了上面的代码以显示我的尝试。再次感谢...
  • 为什么要设置 e.DrawDefault = true?这将透支你所做的任何绘画。
  • 荒谬,小学生的东西!谢谢,绝对的集体行为。一切顺利。
【解决方案2】:

只需将 TreeView 的 HotTracking 设置为 true 即可,因为在 TreeView 中,它包含的节点没有自我标识作为控制,每个节点都由 TreeView 本身绘制,而节点只包含数据,这就是为什么他们没有事件并且 TreeView 可以完成整个工作,所以要设置这些热状态

objTreeView.HotTracking = true;

TreeView 将开始为您提供状态,您的代码将正常工作。

【讨论】:

    猜你喜欢
    • 2014-08-24
    • 2021-01-02
    • 1970-01-01
    • 2017-08-28
    • 1970-01-01
    • 1970-01-01
    • 2017-12-11
    • 2012-08-14
    • 1970-01-01
    相关资源
    最近更新 更多