Existe-t-il un moyen simple de faire en sorte qu'un TreeNode sélectionné conserve ses SystemColors.Highlight BackColor alors que TreeView n'a pas le focus? Parce que même avec HideSelection défini sur false, le BackColor sélectionné est presque impossible à voir.
TreeNode sélectionné lorsque TreeView a le focus:
TreeNode sélectionné alors que TreeView n'a pas le focus:
Merci d'avance.
EDIT: Je suis conscient que je pourrais définir DrawMode sur OwnerDrawAll, puis ajouter un événement DrawNode personnalisé. J'ai déjà essayé de le faire auparavant, le problème est que je ne sais pas comment dessiner correctement l'image correspondante de la TreeNode.
La solution fonctionne comme un charme:
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;
}
}
Si vous souhaitez conserver la couleur d'arrière-plan SystemColors.Highlight
, c'est que vous n'avez pas besoin de définir la propriété TreeView
de DrawMode
sur TreeViewDrawMode.OwnerDrawAll
. Le paramétrer sur TreeViewDrawMode.OwnerDrawText
devrait suffire, vous n'avez donc pas à vous soucier de dessiner la TreeNode
correspondante ImageKey
.
Définissez le TreeView.DrawMode
sur TreeViewDrawMode.OwnerDrawText
:
treeView.DrawMode = TreeViewDrawMode.OwnerDrawText;
Définissez le Treview.HideSelection
sur false
afin que les états de nœud soient conservés tels que sélectionnés:
treeView.HideSelection= false;
Ajoutez le gestionnaire d'événements DrawNode
pour dessiner l'arrière-plan à l'aide de SystemColors.Highlight
color:
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;
}
}
J'utilise cette solution et ça marche mieux
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;
}
}
MODIFIER
Basé sur this documentation,
La valeur par défaut est Color.Empty
Donc, dans treeView1_Enter
il est préférable de définir la couleur comme ceci
treeView1.SelectedNode.BackColor = Color.Empty;
treeView1.SelectedNode.ForeColor = Color.Empty;
Réponse précédente
treeView1.SelectedNode.BackColor = treeView1.BackColor;
treeView1.SelectedNode.ForeColor = treeView1.ForeColor;
si vous avez juste besoin de mettre en évidence le nœud sélectionné lorsque l'arborescence n'est plus au point, utilisez simplement treeView.HideSelection = false;
En réalité, par défaut, le nœud sélectionné est mis en surbrillance mais n'est pas visible. Il suffit donc de définir la propriété HideSelection sur false.
Trouvé cette excellente solution ici (MSDN)
Ca a très bien fonctionné pour moi, j'espère que ça va aider quelqu'un d'autre.
Vous pouvez aussi le personnaliser si vous savez ce que vous faites.
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);
}
}
}
Cette variante de IronGeeks answer fonctionne pour moi et fonctionne avec 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
La principale différence est que le dessin personnalisé est effectué même si la variable TreeView
est activée. Et DrawString()
est utilisé à la place de DrawText()
.
c'est le comportement par défaut pour l'arborescence. Tout ce que vous devez faire pour le changer est d’autoriser le drawode. Il y a une autre réponse de débordement de pile qui l'explique mieux que je ne pourrais le faire ici.
Le code suivant fonctionne même avec des nœuds sélectionnés par programme.
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;
}