2010-01-12 13 views
8

Tengo una aplicación que está conectada a un servidor remoto y datos de sondeo cuando es necesario. Tiene un TreeView donde los Nodos representan los objetos que están disponibles y el color del texto indica si los datos han sido cargados o no; gris-cursiva indica que no está cargado, negro, el texto normal está cargado.Problemas con TreeView.DrawNode - OwnerDrawText

Actualmente tengo presente al TreeView ser OwnderDrawText y tienen la función TreeView.DrawNode simplemente dibujar el texto como tal:

private void TreeViewDrawNode(object sender, DrawTreeNodeEventArgs e) 
{ 
    if (!e.Node.IsVisible) 
    { 
     return; 
    } 

    bool bLoaded = false; 

    if (e.Bounds.Location.X >= 0 && e.Bounds.Location.Y >= 0) 
    { 
     if(e.Node.Tag != null) 
     { 
      //... 
      // code determining whether data has been loaded is done here 
      // setting bLoaded true or false 
      //... 
     } 
     else 
     { 
      e.DrawDefault = true; 
      return; 
     } 

     Font useFont = null; 
     Brush useBrush = null; 

     if (bLoaded) 
     { 
      useFont = e.Node.TreeView.Font; 
      useBrush = SystemBrushes.WindowText; 
     } 
     else 
     { 
      useFont = m_grayItallicFont; 
      useBrush = SystemBrushes.GrayText; 
     } 
     e.Graphics.DrawString(e.Node.Text, useFont, useBrush, e.Bounds.Location); 
    } 
} 

que pensé que sería suficiente, sin embargo, esto ha causado algunos problemas;

  1. Cuando se selecciona un nodo, centrado o no, que no envuelve todo el texto, example (espero imgur está bien).
  2. Cuando el nodo está enfocado, el contorno punteado tampoco aparece. Si lo compara con este example. Los nodos con el "registro" en el texto están utilizando el e.DefaultDraw = verdadero

Intenté seguir el ejemplo dado en la pregunta this. Parecía algo como esto:

private void TreeViewDrawNode(object sender, DrawTreeNodeEventArgs e) 
{ 
    if (!e.Node.IsVisible) 
    { 
    return; 
    } 

    bool bLoaded = false; 

    if (e.Bounds.Location.X >= 0 && e.Bounds.Location.Y >= 0) 
    { 
    if(e.Node.Tag != null) 
    { 
     //... 
     // code determining whether data has been loaded is done here 
     // setting bLoaded true or false 
     //... 
    } 
    else 
    { 
     e.DrawDefault = true; 
     return; 
    } 

    //Select the font and brush depending on whether the property has been loaded 
    Font useFont = null; 
    Brush useBrush = null; 

    if (bLoaded) 
    { 
    useFont = e.Node.TreeView.Font; 
    useBrush = SystemBrushes.WindowText; 
    } 
    else 
    { 
    //member variable defined elsewhere 
    useFont = m_grayItallicFont; 
    useBrush = SystemBrushes.GrayText; 
    } 

    //Begin drawing of the text 

    //Get the rectangle that will be used to draw 
    Rectangle itemRect = e.Bounds; 
    //Move the rectangle over by 1 so it isn't on top of the check box 
    itemRect.X += 1; 

    //Figure out the text position 
    Point textStartPos = new Point(itemRect.Left, itemRect.Top); 
    Point textPos = new Point(textStartPos.X, textStartPos.Y); 

    //generate the text rectangle 
    Rectangle textRect = new Rectangle(textPos.X, textPos.Y, itemRect.Right - textPos.X, itemRect.Bottom - textPos.Y); 

    int textHeight = (int)e.Graphics.MeasureString(e.Node.Text, useFont).Height; 
    int textWidth = (int)e.Graphics.MeasureString(e.Node.Text, useFont).Width; 

    textRect.Height = textHeight; 

    //Draw the highlighted box 
    if ((e.State & TreeNodeStates.Selected) != 0) 
    { 
    //e.Graphics.FillRectangle(SystemBrushes.Highlight, textRect); 
    //use pink to see the difference 
    e.Graphics.FillRectangle(Brushes.Pink, textRect); 
    } 
    //widen the rectangle by 3 pixels, otherwise all of the text  won't fit 
    textRect.Width = textWidth + 3; 

    //actually draw the text 
    e.Graphics.DrawString(e.Node.Text, useFont, useBrush, e.Bounds.Location); 

    //Draw the box around the focused node 
    if ((e.State & TreeNodeStates.Focused) != 0) 
    { 
    textRect.Width = textWidth; 
    Pen focusPen = new Pen(Color.Black); 
    focusPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot; 
    e.Graphics.DrawRectangle(focusPen, textRect); 
    } 
    } 
} 

Sin embargo, los resultados fueron this. (Nota, usó rosa para diferenciar los colores). Como puede ver, el fondo resaltado no se extiende hasta donde está la línea de puntos enfocada. Y también hay otra caja que también se dibuja.

Estoy un poco perplejo sobre cómo solucionar esto. Todo lo que quiero es tener texto en cursiva gris cuando se carga algo. El primer y más simple enfoque no funciona del todo y el segundo método parece que estoy haciendo demasiado.

Después de todo eso, ¿alguien tiene alguna sugerencia sobre cómo hacer esto correctamente, porque tiene que haber una manera más simple.

Gracias de antemano.

+0

Muchas gracias por 'if (! E.Node.IsVisible) return;' ¡Tenía tantos problemas sin él! – Daywalker

Respuesta

14

Tendrá que utilizar TextRenderer.DrawText(). Eso es lo que TreeView usa, lo que hace que el texto sea ligeramente diferente de Graphics.DrawString().

+1

¡Bien, por supuesto que va a ser así de fácil! Eso funcionó por completo, muchas gracias. Ahora, ¿dónde puedo encontrar esta información sobre TreeView usando DrawText? –

+2

Esto todavía no está corrigiendo todos los problemas técnicos de gráficos. Incluso si mi manejador DrawNode simplemente establece DrawDefault en true y lo devuelve inmediatamente, sigue causando que los restos del fondo del rectángulo de selección permanezcan después de que el nodo no se haya seleccionado. Además, el texto está descentrado (verticalmente) al usar DrawMode = OwnerDrawText, incluso cuando DrawDefault es todo lo que se usa. Se debe desplazar un píxel para que coincida con lo que se muestra cuando DrawMode = Normal. El problema es que los métodos de dibujo del control son un híbrido entre el código de dibujo nativo de Windows y el código de dibujo del marco, y son muy inconsistentes. – Triynko