更正覆盖树视图的渲染

本文关键字:视图 覆盖 | 更新日期: 2023-09-27 18:19:45

我在使用标准的Windows窗体TreeView时遇到问题;特别是当树视图没有焦点时,默认控件用来渲染选定节点的颜色。这是一种浅灰色,在一些屏幕上几乎看不见。随后,我对TreeView进行了子类化,并覆盖了TreeView OnDrawNode事件,以便根据自己的意愿为节点着色。这运行得很好,但现在"HotTracking"(当鼠标在给定的树节点上时主动高亮显示)被我的自定义OnDrawNode事件淹没了。我不太熟悉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);
           }   
        }
    }

和往常一样,非常感谢你们抽出时间。

更正覆盖树视图的渲染

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

只需将TreeView的HotTracking设置为true,它就会起作用,因为在TreeView中,它所包含的节点没有自标识作为控件。每个节点都由TreeView自己绘制,而节点只包含数据。这就是为什么它们没有事件,而TreeView完成所有工作,所以要获得这些热状态设置

objTreeView.HotTracking=true;

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