2012-04-05 37 views
23

Gretings.C# WinForms resalta treenode cuando treeview no tiene foco

Estoy haciendo una interfaz para editar escenarios para un juego. Básicamente consiste en eventos, que tienen condiciones y acciones anidadas. Por lo tanto, planeé usar dos vistas de árbol, una para seleccionar el evento y otra para seleccionar la condición/acción dentro del evento para editar.

Ahora, verá, si selecciono un evento (en la vista de árbol izquierda) y luego trato de seleccionar algo en la vista de árbol derecha, la vista de árbol izquierda dejará de mostrar el rectángulo de selección azul. ¡Esto obviamente es malo porque ahora el usuario no sabe qué evento está editando!

La única forma en que encontré para retener algún tipo de información sobre cuál es la selección actual es mediante el uso de SelectedImageIndex, pero esa es solo una pequeña imagen que será diferente.

¿Hay alguna otra manera de resaltar el treenode mientras no hay ningún foco en la vista de árbol? Sé que puedo simplemente Graphics.DrawRectangle o algo así, pero escuché que el dibujo debe hacerse en Paint event y treeview no tiene ningún evento de pintura ... Así que supongo que si lo dibujo en caso de perder el foco, y luego arrastro el formulario fuera de la pantalla o algo así, será "borrado"?

De todos modos, por favor dígame si usted tiene una idea (con excepción de usar un icono independiente para el seleccionado y no seleccionado NodoArbol)

Gracias!

+0

la imagen que ha enviado ha desaparecido. ¿Tienes una copia en alguna parte? Mientras tanto, eliminaré el enlace ... –

Respuesta

49

Lo que usted está buscando es el HideSelection propiedad en el TreeView.

De MSDN:

Obtiene o establece un valor que indica si el nodo del árbol seleccionado permanece resaltado incluso cuando la vista de árbol ha perdido el foco.

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

Código:

TreeView.HideSelection = false; 
+12

en Windows 7 con esquema de color predeterminado Esto no ayuda: cuando treeview pierde el foco, el nodo seleccionado parece no seleccionado y no puedo ver la diferencia desde otros nodos. – oleksa

14

Todavía se muestra, pero sólo en gris claro, que dependiendo de su pantalla y la configuración actual puede estar cerca en el visible!

Anule el evento OnDrawNode. Entonces crea y nueva clase (llámese "SpecialTreeView") una herencia de Microsoft TreeView como class SpecialTreeView : TreeView. Luego se agrega el siguiente caso de anulación:

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); 
     } 
    } 
} 

compilar el código y debería ver "SpecialTreeView" en su caja de herramientas en el diseñador. Reemplace su TreeView con este nuevo usando el mismo nombre y lo único que será diferente son los colores de selección. Cuando se seleccione, será selectedColor, cuando no se seleccione deselectedColor.

Espero que esto ayude.

+0

Sí, lo hace, pero solo que no :) A menos que establezca HideSelection en falso, que es verdadero de manera predeterminada (¿para qué? ... eh, negocio M $ típico). Gracias por su consejo de todos modos, no me di cuenta de que tiene el evento "DrawNode", estaba buscando un evento típico de Paint ... – Istrebitel

+0

Huh .... it .... wont fire! Ya estoy usando el control TreeView personalizado porque la base uno no tiene capacidades de arrastrar y soltar ... Sobrescribir OnDragDrop, OnDragEnter funciona ... reemplazando a este no. Simplemente no se ejecuta, he puesto un punto de interrupción, nada. ¿Qué puede estar mal? – Istrebitel

+1

Ah sí, lo encontré. Su DrawMode, si está configurado en Normal, el evento no se disparará. – Istrebitel

7

No es una solución absolutamente perfecto, pero bastante cerca de:

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; 
}; 
+1

Gracias, esto ayudó. Aunque cambié Brushes.Gray a SystemBrushes.Highlight – GeoffCoope

9

Solución rápida:

Ajuste las propiedades:

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

Luego, en el controlador de eventos DrawNode simplemente hacer:

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

En Windwos 7 Esto restaura la antigua prestación, incluyendo la caja de puntos alrededor de la selección (que en realidad parece un poco obsoleta). El texto será blanco con enfoque y negro sin foco. El fondo se mantiene azul y visible.

Esta respuesta no es nueva, los demás también contienen estos pasos, pero este es el mínimo necesario (al menos en Windows 7, no se probaron otros sistemas operativos).

+0

Me gusta, excepto por dos problemas: 1) El icono de casilla de verificación se corta en el lado derecho, y 2) parece significativamente más lento al marcar/desmarcar .... – AndrewRalon

Cuestiones relacionadas