Treeview (Windows forms) texts become bold when the treeview is loading

86 Views Asked by At

I use a treeview (Windows forms) in an application which has the weird tendency to show bold texts when loading:

enter image description here

When the treeview is fully loaded the texts are shown normal:

enter image description here

I want to prevent that the texts become bold during loading.

So to give some technical background information: what I use for the treeview is the TreeviewDrawMode -> OwnerDrawText :

trvScheduling.DrawMode = TreeViewDrawMode.OwnerDrawText;

And in the treeview OnDrawNode event I use the following code:

 protected override void OnDrawNode(DrawTreeNodeEventArgs e)
 {
     if (e.Node == null) return;
     if (e.Node.IsVisible == false) return;

     var selected = (e.State & TreeNodeStates.Selected) == TreeNodeStates.Selected;
     //var unfocused = !e.Node.TreeView.Focused;

     if (e.Node.TreeView.CheckBoxes == false)
     {
         // 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)
         {
             var font = e.Node.NodeFont ?? e.Node.TreeView.Font;
             Brush solidBrush = new SolidBrush(WinFormsUITheme.styleColor);
             e.Graphics.FillRectangle(solidBrush, e.Bounds);
             TextRenderer.DrawText(e.Graphics, e.Node.Text, font, e.Bounds, Color.White, TextFormatFlags.GlyphOverhangPadding);
         }
         else
         {
             e.DrawDefault = true;
         }
     }
     else
     {
         //if (e.Node == null) return;

         if ((e.State & TreeNodeStates.Selected) != 0)
         {
             var font = e.Node.NodeFont ?? e.Node.TreeView.Font;
             Brush solidBrush = new SolidBrush(Color.White);
             e.Graphics.FillRectangle(solidBrush, new Rectangle(e.Bounds.Left, e.Bounds.Top, e.Bounds.Right, 16));
         }

         //Use the default background and node text.
         else
         {
             //e.DrawDefault = true;
         }

         // If a node tag is present, draw its string representation 
         // to the right of the label text.
         if (e.Node.ToolTipText != null)
         {
             //e.Node.Text

             int color;
             bool isValidInt = int.TryParse(e.Node.ToolTipText.ToString(), out color);

             if (isValidInt)
             {
                 Brush colorBrush = new SolidBrush(Color.FromArgb(color));
                 //e.Graphics.FillRectangle(colorBrush, new Rectangle(e.Bounds.Right + 2, e.Bounds.Top, 10, 10));

                 e.Graphics.FillRectangle(colorBrush, new Rectangle(e.Bounds.Left + 2, e.Bounds.Top + 2, 10, 10));

                 e.Graphics.DrawString(e.Node.Text.ToString(), tagFont,
                 Brushes.Black, e.Bounds.Left + 12, e.Bounds.Top);
             }
             else
             {
                 e.DrawDefault = true;
             }
         }
     }
 }

I wonder if maybe something goes 'wrong' in the OnDrawNode event which causes these 'bold' texts during the loading of the treeview. Does anybody know what causes this?

I have tried to apply: 'e.Graphics.TextRenderingHint = TextRenderingHint.AntiAlias' before the 'e.Graphics.DrawString( ..' method but this doesn't solve it. However If I set a debug breakpoint in the OnDrawNode event I noticed that the treeview draws each node text three times. The first time the text is set right but the second round the text becomes bold because the same text is rendered twice then. Does anybody know how to prevent this from happening in the OnDrawNode event?

2

There are 2 best solutions below

0
r-m85 On

Thank you lork6. I have drawn another rectangle in the OnDrawNode event which size represents the node bounds:

 e.Graphics.FillRectangle(new SolidBrush(Color.Black), new Rectangle(e.Bounds.Left, e.Bounds.Top, e.Bounds.Width, e.Bounds.Height));

...and this indeed shows the node texts fall outside of the bounds (because of the colored rectangle):

enter image description here

So you say this is the reason for the bold texts? How can I prevent the texts from falling outside of the bounds? Maybe by using a smaller font (then the original set font) in the OnDrawNode event?

By the way I have tried to apply this before drawing the text in the OnDrawNode event:

 e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit

... but this didn't solve it.

1
lork6 On
private Rectangle NodeBounds(TreeNode node)
{
    int ColoredRectWidth = 12;
    Rectangle bounds = node.Bounds;
    if(node.Text != null)
    {
        Graphics g = this.CreateGraphics();
        int tagwidth = (int)g.MeasureString(node.Text, Font).Width+ ColoredRectWidth;

        bounds.Offset(tagwidth/2,0);
        bounds = Rectangle.Inflate(bounds,tagwidth/2,0);
        g.Dispose();
    }
    return bounds;
}

This needs to be added. This calculate the text bounds. Then Before you draw anything you have to clear the background.

e.Graphics.FillRectangle(Brushes.White, NodeBounds(e.Node));

Source

Eliminate the flicker add this to the TreeView:

protected override void OnHandleCreated(EventArgs e) {
       SendMessage(this.Handle, TVM_SETEXTENDEDSTYLE, (IntPtr)TVS_EX_DOUBLEBUFFER, (IntPtr)TVS_EX_DOUBLEBUFFER);
        base.OnHandleCreated(e);
    }
    // Pinvoke:
    private const int TVM_SETEXTENDEDSTYLE = 0x1100 + 44;
    private const int TVM_GETEXTENDEDSTYLE = 0x1100 + 45;
    private const int TVS_EX_DOUBLEBUFFER = 0x0004;
    [DllImport("user32.dll")]
    private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);

Source