当树视图没有焦点时,C# WinForms 突出显示树节点

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10034714/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 12:13:01  来源:igfitidea点击:

C# WinForms highlight treenode when treeview doesnt have focus

c#winformstreeviewtreenode

提问by Istrebitel

Gretings.

问候。

I'm making an interface to edit scenarios for a game. Basically it consists of events, which have nested conditions and actions. So, i planned using two treeviews - one for selecting the event, and other for selecting the condition/action inside the event to edit.

我正在制作一个界面来编辑游戏的场景。基本上它由具有嵌套条件和动作的事件组成。因此,我计划使用两个树视图 - 一个用于选择事件,另一个用于选择事件内的条件/操作进行编辑。

Now, you see, if i select an event (in left treeview) and then try to select something in the right treeview, the left treeview will stop showing the blue selection rectangle. This is obviously bad because now the user doesnt know which event is he editing!

现在,你看,如果我选择一个事件(在左树视图中),然后尝试在右树视图中选择一些东西,左树视图将停止显示蓝色选择矩形。这显然很糟糕,因为现在用户不知道他正在编辑哪个事件!

The only way i found to retain some sort of information about what is the current selection is by using SelectedImageIndex, but thats only one little image that will be different.

我发现保留有关当前选择的某种信息的唯一方法是使用 SelectedImageIndex,但这只是一个不同的小图像。

Is there any other way to highlight the treenode while there is no focus on the treeview? I know i can just Graphics.DrawRectangle or something, but i heard that drawing should be done in Paint event and treeview has no paint event... So i guess if i draw it on the event of losing focus, and then drag the form out of the screen or something, it will be "erased"?

在没有关注树视图的情况下,还有其他方法可以突出显示树节点吗?我知道我可以只是 Graphics.DrawRectangle 或其他东西,但我听说绘图应该在 Paint 事件中完成,而 treeview 没有 Paint 事件......所以我想如果我在失去焦点的事件上绘制它,然后拖动表单出屏幕什么的,会不会被“抹掉”?

Anyway, please tell me if you got an idea (other than using a separate icon for selected and not selected treenode)

无论如何,请告诉我您是否有想法(除了为选定和未选定的树节点使用单独的图标之外)

Thanks!

谢谢!

采纳答案by aKzenT

What you are looking for is the HideSelectionproperty on the TreeView.

你要找的是HideSelection对物业TreeView

From MSDN:

来自 MSDN:

Gets or sets a value indicating whether the selected tree node remains highlighted even when the tree view has lost the focus.

获取或设置一个值,该值指示选定的树节点是否在树视图失去焦点时仍保持突出显示。

Link: http://msdn.microsoft.com/en-us/library/system.windows.forms.treeview.hideselection.aspx

链接:http: //msdn.microsoft.com/en-us/library/system.windows.forms.treeview.hideselection.aspx

Code:

代码:

TreeView.HideSelection = false;

回答by MoonKnight

It is still shown but only in light grey which depending on your screen and current setup can be near in visible!

它仍然显示,但仅以浅灰色显示,这取决于您的屏幕和当前设置可以接近可见!

Override the OnDrawNode event. So you create and new class (call it "SpecialTreeView") an inherit from the Microsoft TreeViewlike class SpecialTreeView : TreeView. Then you add the following event override:

覆盖 OnDrawNode 事件。因此,您创建和新类(称为“SpecialTreeView”)继承自 Microsoft 之TreeView类的class SpecialTreeView : 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";
    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, 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, 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
    {
        if ((e.State & TreeNodeStates.Hot) == TreeNodeStates.Hot)
        {
            e.Graphics.FillRectangle(SystemBrushes.Window, e.Bounds);
            TextRenderer.DrawText(e.Graphics, e.Node.Text, hotFont, e.Bounds,
                                         System.Drawing.Color.Black, TextFormatFlags.GlyphOverhangPadding);
        }
        else
        {
            e.Graphics.FillRectangle(SystemBrushes.Window, e.Bounds);
            TextRenderer.DrawText(e.Graphics, e.Node.Text, treeFont, e.Bounds,
                                         foreColor, TextFormatFlags.GlyphOverhangPadding);
        }
    }
}

Compile the code and you should see "SpecialTreeView" in your tool box in the designer. Replace your TreeView with this new one using the same name and the only thing that will be different is the selection colours. When selected it will be selectedColor, when not selected the deselectedColor.

编译代码,您应该会在设计器的工具箱中看到“SpecialTreeView”。使用相同的名称将您的 TreeView 替换为这个新的,唯一不同的是选择颜色。选中时会selectedColor,未选中时deselectedColor

I hope this helps.

我希望这有帮助。

回答by Bachor

Not absolutely perfect solution, but quite near:

不是绝对完美的解决方案,但非常接近:

treeView.HideSelection = false;
treeView.DrawMode = TreeViewDrawMode.OwnerDrawText;
treeView.DrawNode += (o, e) =>
{
    if (!e.Node.TreeView.Focused && e.Node == e.Node.TreeView.SelectedNode)
    {
        Font treeFont = e.Node.NodeFont ?? e.Node.TreeView.Font;
        e.Graphics.FillRectangle(Brushes.Gray, e.Bounds);
        ControlPaint.DrawFocusRectangle(e.Graphics, e.Bounds, SystemColors.HighlightText, SystemColors.Highlight);
        TextRenderer.DrawText(e.Graphics, e.Node.Text, treeFont, e.Bounds, SystemColors.HighlightText, TextFormatFlags.GlyphOverhangPadding);
    }
    else
        e.DrawDefault = true;
};
treeView.MouseDown += (o, e) =>
{
    TreeNode node = treeView.GetNodeAt(e.X, e.Y);
    if (node != null && node.Bounds.Contains(e.X, e.Y))
        treeView.SelectedNode = node;
};

回答by Louis Somers

Fast solution:

快速解决方案:

Set the properties:

设置属性:

  • HideSelection = false;
  • DrawMode = TreeViewDrawMode.OwnerDrawText;
  • HideSelection = false;
  • DrawMode = TreeViewDrawMode.OwnerDrawText;

Then in the DrawNode event handler simply do:

然后在 DrawNode 事件处理程序中简单地做:

private void treeView1_DrawNode(object sender, DrawTreeNodeEventArgs e) {
  e.DrawDefault = true;
}

On Windwos 7 this restores the old rendering, including the dashed box around the selection (which actually looks a bit outdated). The text will be white with focus, and black without focus. The background stays blue and visible.

在 Windwos 7 上,这会恢复旧的渲染,包括选择周围的虚线框(实际上看起来有点过时)。文本在有焦点时为白色,无焦点时为黑色。背景保持蓝色且可见。

This answer is not new, the others also contain these steps, but this is the minimal needed (at least in Windows 7, didn't test other OS's).

这个答案并不新鲜,其他答案也包含这些步骤,但这是最少需要的(至少在 Windows 7 中,没有测试其他操作系统)。

回答by Ivan

Similar to the previous one but with the appearance more similar to the Win10 standard:

与上一个相似,但外观更接近Win10标准:

treeView.HideSelection = false;
treeView.DrawMode = TreeViewDrawMode.OwnerDrawText;

treeView.DrawNode += (o, e) =>
{
    if (e.Node == e.Node.TreeView.SelectedNode)
    {
        Font font = e.Node.NodeFont ?? e.Node.TreeView.Font;
        Rectangle r = e.Bounds;
        r.Offset(0, 1);
        Brush brush = e.Node.TreeView.Focused ? SystemBrushes.Highlight : Brushes.Gray;
        e.Graphics.FillRectangle(brush, e.Bounds);
        TextRenderer.DrawText(e.Graphics, e.Node.Text, font, r, SystemColors.HighlightText, TextFormatFlags.GlyphOverhangPadding);
    }
    else
        e.DrawDefault = true;
};

treeView.MouseDown += (o, e) =>
{
    TreeNode node = treeView.GetNodeAt(e.Location);
    if (node != null && node.Bounds.Contains(e.Location)) treeView.SelectedNode = node;
};

回答by Sam

Found an easier way:

找到了一个更简单的方法:

  1. Set TreeView.HideSelection = True
  2. Add the following to TreeView.AfterSelect-Callback:
    private void treeViewBenutzerverwaltung_AfterSelect(object sender, TreeViewEventArgs e)
    {
        // Select new node
        e.Node.BackColor = SystemColors.Highlight;
        e.Node.ForeColor = SystemColors.HighlightText;
        if (_lastSelectedNode != null)
        {
            // Deselect old node
            _lastSelectedNode.BackColor = SystemColors.Window;
            _lastSelectedNode.ForeColor = SystemColors.WindowText;
        }
        lastSelectedNode = e.Node;
    }
    
  1. 设置 TreeView.HideSelection = True
  2. 将以下内容添加到 TreeView.AfterSelect-Callback:
    private void treeViewBenutzerverwaltung_AfterSelect(object sender, TreeViewEventArgs e)
    {
        // Select new node
        e.Node.BackColor = SystemColors.Highlight;
        e.Node.ForeColor = SystemColors.HighlightText;
        if (_lastSelectedNode != null)
        {
            // Deselect old node
            _lastSelectedNode.BackColor = SystemColors.Window;
            _lastSelectedNode.ForeColor = SystemColors.WindowText;
        }
        lastSelectedNode = e.Node;
    }