2

I am using Microsoft Visual Studio Community 2017 version 15.7.2, and .NET Framework version 4.7.03056.

I am using the Winforms TreeView and am modifying its default behavior to make it a little bit more like the Windows Explorer tree view. I set the following properties:

LineHeight`    22
DrawMode       OwnerDrawAll

I am using the following for the DrawNode event. This code uses right and down bracket bitmaps (which are 16x16) to show expanded or unexpanded nodes, and uses custom colors for select/focus highlighting. Nothing exotic.

private void treeDir_DrawNode(object sender, DrawTreeNodeEventArgs e)
{
    const int indent = 12;
    const int markerSpacing = 20;

    int leftPos = e.Bounds.Left + e.Node.Level * indent;
    Brush selectBrush;
    Pen pen;
    Graphics g = e.Graphics;

    e.DrawDefault = false;

    if (e.Node.IsSelected)
    {
        if (e.Node.TreeView.Focused)
        {
            selectBrush = new SolidBrush(FocusedBackgroundColor);
            pen = new Pen(new SolidBrush(FocusedPenColor));
        }
        else
        {
            selectBrush = new SolidBrush(UnfocusedBackgroundColor);
            pen = new Pen(new SolidBrush(UnfocusedPenColor));
        }

        g.FillRectangle(selectBrush, e.Bounds);
        g.DrawRectangle(pen, e.Bounds);
    }

    if (e.Node.Nodes.Count > 0)
    {
        if (e.Node.IsExpanded)
        {
            g.DrawImage(Properties.Resources.Expanded, leftPos+2, e.Bounds.Top+2);
        }
        else
        {
            g.DrawImage(Properties.Resources.Unexpanded, leftPos+2, e.Bounds.Top+2);
        }
    }

    g.DrawString(
        e.Node.Text, CommonFont, new SolidBrush(Color.Black), leftPos + markerSpacing, e.Bounds.Top+2);
}

What's happening is that when the form is first shown, if I expand a node that is not the first node, it also overwrites (transparently overlays) the first node text. Here's the sequence.

On start up of the form:

enter image description here

Then I double click Node 4:

enter image description here

If I double click the first node, the problem clears up:

enter image description here

From this point forward, if I double click Node 4, the problem no longer occurs. Double clicking the first node clears up the problem and avoids it for the life of the form after that point for Node 4. However, if I double click another expandable node further down, it happens again.

Is this a bug in TreeView or am I doing something incorrect in my owner draw?

TaW
  • 53,122
  • 8
  • 69
  • 111
lurker
  • 56,987
  • 9
  • 69
  • 103
  • The bounds of the node do not seems to be defined properly when you are reading them. I personally never used it and use the item height of the control instead. – Franck Jun 12 '18 at 11:18
  • 1
    @Franck but I need the `e.Bounds` to get the proper starting position of the rectangle. The control item height is not enough information to do the drawing. The canvas of `e.Graphics` is the entire `TreeView` control, not just the node. If I don't use `e.Bounds`, how else would I find the bounds of the node? – lurker Jun 12 '18 at 11:21
  • You are right. I mistaken the treeview ondraw and the node ondraw. I have the solution ill post the answer. – Franck Jun 12 '18 at 11:53

1 Answers1

2

The DrawNode event is called rather too often when doubleclicking and one set of calls has a bounds rectangle that is Empty.

(Maybe the reasoning was: If all drawing is happening only in the empty rectangle nothing will show. Hm..)

So as a workaround you can shortcut the DrawNode event for all the wrong calls at the beginning of the event:

if (e.Bounds.Height < 1 || e.Bounds.Width < 1) return;

I also recommend text rendering like this..:

TextRenderer.DrawText(g, e.Node.Text, CommonFont, 
                      new Point( leftPos + markerSpacing, e.Bounds.Top+2), Color.Black);

TextRenderer is always recommended over Graphics.DrawString for forms as it improves on several shortcomings.

TaW
  • 53,122
  • 8
  • 69
  • 111
  • Yes it does seem I'm getting an extra incorrect draw event. I'll tinker with this hack. – lurker Jun 12 '18 at 12:04
  • Actually I have improved on it with an observation from [this post](https://stackoverflow.com/questions/1003459/c-treeview-owner-drawing-with-ownerdrawtext-and-the-weird-black-highlighting-w) – TaW Jun 12 '18 at 12:05
  • 1
    Thanks for the update. It's funny, I read the link you gave and the author of that answer uses the defensive check for `Height` and `Width` without comment. In other scenarios in my code I have used `TextRenderer` and found that it overcame some issues. I guess I was being a little lazy and just threw in a `DrawString` call in this event. Thanks for the nudge back to `TextRenderer`. :) – lurker Jun 12 '18 at 12:17