The goal is to ensure that the text of the TreeView nodes is drawn with its own code. As follows from the description, for this you need to set the DrawMode property in OwnerDrawText and write code to handle the DrawNode event. However, I was faced with the situation that decisions in the forehead do not lead to the expected effect in the proper measure, i.e. There are some shifts, artifacts or text alignment problems.

For example, the following code:

 private void treeView1_DrawNode(object sender, DrawTreeNodeEventArgs e) { if ((e.State & TreeNodeStates.Selected) != 0) { e.Graphics.FillRectangle(Brushes.Green, e.Node.Bounds); Font nodeFont = e.Node.NodeFont; if (nodeFont == null) nodeFont = ((TreeView)sender).Font; e.Graphics.DrawString(e.Node.Text, nodeFont, Brushes.White, e.Bounds); } else { e.DrawDefault = true; } } 

leads to the loss of the last character of the text when selected in the child nodes and the text slightly shifted to the left:

curve drawing

From the answer to a similar topic on enSO, this can be explained by the need to use TextRenderer.DrawText() instead of Graphics.DrawString() . But in this case there is also some shift of the text to the left. Code:

 private void treeView1_DrawNode(object sender, DrawTreeNodeEventArgs e) { if ((e.State & TreeNodeStates.Selected) != 0) { e.Graphics.FillRectangle(Brushes.Green, e.Node.Bounds); Font nodeFont = e.Node.NodeFont; if (nodeFont == null) nodeFont = ((TreeView)sender).Font; TextRenderer.DrawText(e.Graphics, e.Node.Text, nodeFont, e.Node.Bounds, Color.White); } else { e.DrawDefault = true; } } 

gives the following (almost appropriate) result:

almost correct

In general, I want to understand how to do everything right, and ideally find the code that provides the drawing when e.DrawDefault = true; . In this case, you can tweak it to fit your needs.

  • Judging by the corrupted square and the remnants of the text "ot" from the word Root, you didn’t print the text, you need to correctly calculate the indent, display the text to the right in the DrawText function. - nick_n_a
  • @nick_n_a, yes, here I imposed a little, corrected the code in question and the conclusion, but still there is a shift in the text when selected. - αλεχολυτ
  • one
    Exclude the left border from e.Node.Bounds and move a couple of pixels) - nick_n_a
  • @nick_n_a expanded by 1px. It seems to be the truth. - αλεχολυτ

1 answer 1

You need to move the drawing rectangle up 1 pixel, then the text will be displayed in the same place:

 var rect = e.Bounds; rect.Y--; TextRenderer.DrawText(e.Graphics, e.Node.Text, nodeFont, rect, Color.White); 

But getting the sources of how DrawMode = Normal works DrawMode = Normal still be nice.

  • They work simply, using WinAPI from user32.dll DrawTextW, in the Windows SDK in the TreeViews section (Common Controls section) there is a similarly weak description of the methods. The <windows.h> library. And TextRenderer.DrawText is just a bridge between a machine with # (CLR) and WinAPI. And the sources of the core of Windows - maybe somewhere already lying around. - nick_n_a
  • @nick_n_a is understandable, but I would like a clear sequence of calls, because it is not clear why you need to do all sorts of single-pixel shifts, for example. And for some reason, the selection of the text (in classic blue) still happens, i.e. You need to explicitly rub the rectangle with the background color first, and then do the rest. - αλεχολυτ
  • one
    Perhaps in fact, 1 pixel from 4 sides is occupied by the focus frame, which is drawn DrawFocusRect (WinAPI) System.Windows.Forms.ControlPaint.DrawFocusRectangle. In your picture just it is not enough. - nick_n_a