【问题标题】:TreeNode Selected BackColor while TreeView not focusedTreeNode 在 TreeView 未聚焦时选择了 BackColor
【发布时间】:2014-01-18 00:52:37
【问题描述】:

是否有一种简单的方法可以让选定的 TreeNode 在 TreeView 没有焦点时保留其 SystemColors.Highlight BackColor?因为即使 HideSelection 设置为 false,所选的 BackColor 也几乎无法看到。

TreeView 具有焦点时选定的 TreeNode:

TreeView 没有焦点时选定的 TreeNode:

提前致谢。

编辑: 我知道我可以将 DrawMode 设置为 OwnerDrawAll,然后添加一个自定义 DrawNode 事件。我之前确实尝试过,我遇到的问题是我不知道如何正确绘制 TreeNode 的相应 ImageKey。

【问题讨论】:

    标签: c# winforms treeview custom-draw


    【解决方案1】:

    如果您只需要保留SystemColors.Highlight 背景颜色,则无需将TreeViewDrawMode 属性设置为TreeViewDrawMode.OwnerDrawAll。将其设置为TreeViewDrawMode.OwnerDrawText 就足够了,因此您无需担心绘制TreeNode 对应的ImageKey

    1. TreeView.DrawMode 设置为TreeViewDrawMode.OwnerDrawText

      treeView.DrawMode = TreeViewDrawMode.OwnerDrawText;
      
    2. Treview.HideSelection设置为false,这样节点状态将保持为选中状态:

      treeView.HideSelection= false;
      
    3. 添加DrawNode事件处理程序以使用SystemColors.Highlight颜色绘制背景:

      private void treeView_DrawNode(object sender, DrawTreeNodeEventArgs e)
      {
        if (e.Node == null) return;
      
        // if treeview's HideSelection property is "True", 
        // this will always returns "False" on unfocused treeview
        var selected = (e.State & TreeNodeStates.Selected) == TreeNodeStates.Selected;
        var unfocused = !e.Node.TreeView.Focused;
      
        // we need to do owner drawing only on a selected node
        // and when the treeview is unfocused, else let the OS do it for us
        if (selected && unfocused)
        {
          var font = e.Node.NodeFont ?? e.Node.TreeView.Font;
          e.Graphics.FillRectangle(SystemBrushes.Highlight, e.Bounds);
          TextRenderer.DrawText(e.Graphics, e.Node.Text, font, e.Bounds, SystemColors.HighlightText, TextFormatFlags.GlyphOverhangPadding);
        }
        else
        {
          e.DrawDefault = true;
        }
      }
      

    【讨论】:

    • 我在阅读您的答案前 2 分钟才想出了如何做到这一点,我想接受您的答案,所以我想我最好先尝试一下,但它没有用。解决方法可以在上面找到。
    • 哎呀,你是对的。我忘了添加关于HideSelection 属性的部分。我已经更新了答案...
    • 不幸的是,只有在 FullRowSelect 为 false 时才能正常工作,否则选择时会出现奇怪的闪烁,然后只保留文本的背景,而不是整行。
    • @Spark:我没有看到任何闪烁。但是如果使用复选框,复选框的右边框会被文本隐藏。 (.net 4.8,Win 10 x64)。如果使用 FullRowSelect(不仅启用,而且还使用:仅在关闭 TreeLines 时使用),文本根据需要为蓝色,但行的其余部分为浅灰色。
    【解决方案2】:

    解决方案,就像一个魅力:

    public TreeNode previousSelectedNode = null;
    private void treeView1_Validating(object sender, System.ComponentModel.CancelEventArgs e)
    {
        treeView1.SelectedNode.BackColor = SystemColors.Highlight;
        treeView1.SelectedNode.ForeColor = Color.White;
        previousSelectedNode = treeView1.SelectedNode;
    }
    
    private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
    {
        if(previousSelectedNode != null)
        {
            previousSelectedNode.BackColor = treeView1.BackColor;
            previousSelectedNode.ForeColor = treeView1.ForeColor;
        }
    }
    

    【讨论】:

    • 仅供参考,以编程方式设置所选项目时失败(解决方案:手动调用事件)。
    • 请注意,这仅在 HideSelection 为 True(默认值)时才有效!
    • 这对我来说根本不起作用 - 节点仍然几乎不可见......下面的下一个答案(处理 drawnode)似乎完美地工作
    【解决方案3】:

    我用这个解决方案,效果更好

    private void treeView1_Enter(object sender, EventArgs e)
    {
       if (treeView1.SelectedNode != null)
       {
           treeView1.SelectedNode.BackColor = Color.Empty;
           treeView1.SelectedNode.ForeColor = Color.Empty;
       }
    }
    
    private void treeView1_Leave(object sender, EventArgs e)
    {
       if (treeView1.SelectedNode != null)
       {
           treeView1.SelectedNode.BackColor = SystemColors.Highlight;
           treeView1.SelectedNode.ForeColor = Color.White;
       }
    }
    

    编辑

    基于this 文档,

    默认是 Color.Empty

    所以,在treeView1_Enter 中最好这样设置颜色

    treeView1.SelectedNode.BackColor = Color.Empty;
    treeView1.SelectedNode.ForeColor = Color.Empty;
    

    上一个答案

    treeView1.SelectedNode.BackColor = treeView1.BackColor;
    treeView1.SelectedNode.ForeColor = treeView1.ForeColor;
    

    【讨论】:

    • 很好的答案,谢谢。请注意,这仅在 HideSelection 为 True(默认值)时才有效
    • 很好的答案,谢谢!但是,如果在树视图未聚焦时更改了所选节点(通过代码),则它不起作用。这可以通过使用事件 BeforeSelect 和 AfterSelect 来解决。
    • 如果结合@Joh 的建议,最简单和最有效的解决方案。
    【解决方案4】:

    如果您只需要在树视图失焦时突出显示选定的节点,那么只需使用 treeView.HideSelection = false;

    实际上默认选中的节点是高亮的,但不可见,所以我们只需要将 HideSelection 属性设置为 false。

    【讨论】:

    • 问题是,正如问题所提到的,即使 HideSelection = false,当树视图没有焦点时,所选节点也几乎无法与其他节点区分开来。
    【解决方案5】:

    找到了这个很棒的解决方案here (MSDN)

    对我很有帮助,希望对其他人有所帮助。

    1. 向您的项目添加一个新类(名为 MyTreeView.cs 的文件)并粘贴如下所示的代码。
    2. 编译。
    3. 将名为“MyTreeView”的新控件从工具箱顶部拖放到表单上。

    如果你知道自己在做什么,你也可以自定义它

    using System;
    using System.Drawing;
    using System.Windows.Forms;
    
    
    
    class MyTreeView : TreeView {
        public MyTreeView() {
            this.DrawMode = TreeViewDrawMode.OwnerDrawText;
        }
        protected override void OnDrawNode(DrawTreeNodeEventArgs e) {
            TreeNodeStates state = e.State;
            Font font = e.Node.NodeFont ?? e.Node.TreeView.Font;
            Color fore = e.Node.ForeColor;
            if (fore == Color.Empty) fore = e.Node.TreeView.ForeColor;
            if (e.Node == e.Node.TreeView.SelectedNode) {
                fore = SystemColors.HighlightText;
                e.Graphics.FillRectangle(SystemBrushes.Highlight, e.Bounds);
                ControlPaint.DrawFocusRectangle(e.Graphics, e.Bounds, fore, SystemColors.Highlight);
                TextRenderer.DrawText(e.Graphics, e.Node.Text, font, e.Bounds, fore, TextFormatFlags.GlyphOverhangPadding);
            }
            else {
                e.Graphics.FillRectangle(SystemBrushes.Window, e.Bounds);
                TextRenderer.DrawText(e.Graphics, e.Node.Text, font, e.Bounds, fore, TextFormatFlags.GlyphOverhangPadding);
            }
        }
    }
    

    【讨论】:

      【解决方案6】:

      这是树视图的默认行为。更改它所需要做的就是覆盖drawnode。还有另一个堆栈溢出答案比我在这里解释得更好。

      How to change background color of selected node in TreeView using TreeViewDrawMode.OwnerDrawAll?

      【讨论】:

        【解决方案7】:

        以下代码甚至可以使用以编程方式选择的节点。

        public TreeNode m_previousSelectedNode = null;
        private void m_treeView_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (m_previousSelectedNode != null)
            {
                m_previousSelectedNode.BackColor = m_treeView.BackColor;
                m_previousSelectedNode.ForeColor = m_treeView.ForeColor;
            }
        
            e.Node.BackColor = SystemColors.Highlight;
            e.Node.ForeColor = Color.White;
        
            m_previousSelectedNode = m_treeView.SelectedNode;
        }
        

        【讨论】:

        • 如果没有选择问题的重点所在的树,这似乎不起作用。
        【解决方案8】:

        IronGeeks 答案的这个变体适用于我,并且适用于 Bold Nodes

        Private Sub TreeView1_DrawNode(sender As Object, e As DrawTreeNodeEventArgs) Handles trvIdent.DrawNode
            Dim treeView = e.Node.TreeView
            Dim selected = (e.Node Is treeView.SelectedNode)
            Dim unfocused = Not treeView.Focused
            Dim font = If(e.Node.NodeFont IsNot Nothing, e.Node.NodeFont, treeView.Font)
            Dim textSize = e.Graphics.MeasureString(e.Node.Text, font)
            Dim bounds = New Rectangle(e.Bounds.X, e.Bounds.Y,
                                       Convert.ToInt32(textSize.Width),
                                       Math.Max(Convert.ToInt32(textSize.Height), e.Bounds.Height))
        
            e.DrawDefault = False
        
            If selected Then
                e.Graphics.FillRectangle(SystemBrushes.Highlight, bounds)
                e.Graphics.DrawString(e.Node.Text, font, SystemBrushes.HighlightText, bounds.Location)
            Else
                e.Graphics.FillRectangle(SystemBrushes.Window, bounds)
                e.Graphics.DrawString(e.Node.Text, font, SystemBrushes.WindowText, bounds.Location)
            End If
            'e.Graphics.DrawRectangle(Pens.Magenta, bounds)
        End Sub
        

        主要区别在于即使TreeView 被聚焦,自定义绘图也会完成。并且使用DrawString() 代替DrawText()

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-07-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-10-13
          • 2019-05-15
          • 1970-01-01
          • 2013-06-22
          相关资源
          最近更新 更多