Click here to Skip to main content
13,300,002 members (62,480 online)
Click here to Skip to main content
Add your own
alternative version


34 bookmarked
Posted 25 May 2005

Custom Draw TreeView in VB.NET

, 25 May 2005
Rate this:
Please Sign up or sign in to vote.
An owner draw implementation of a VB.NET treeview to show some bold text in nodes.


This article shows the owner draw technique for a TreeView using Visual Basic .NET to draw some portions of the text of the nodes in bold font, as shown in the image.


The owner draw technique for Windows Common Controls is well documented in the following MSDN article: Customizing a Control's Appearance Using Custom Draw&, which I recommend to read. The article explains the notification messages, the paint cycles and drawing stages, and provides a C++ example, so I won't repeat it here.

Using the code

A TreeNodeEx class (derived from TreeNode) is provided in the source code, which allows you to specify in the constructor the node text, the initial text position that will use the bold font, and the length of the bold text.

A helper function like this is provided to add nodes to a TreeView:

Private Function AddNodeToTreeView(ByVal colNodes As TreeNodeCollection, _
     ByVal sText As String, ByVal iBoldTextInitialPosition As Integer, _
     ByVal iBoldTextLength As Integer) As TreeNodeEx

   Dim objTreeNodeEx As TreeNodeEx

   objTreeNodeEx = New TreeNodeEx(sText, _
                   iBoldTextInitialPosition, iBoldTextLength)

   Return objTreeNodeEx

End Function

A TreeViewEx class (derived from TreeView) is provided too. This class performs the owner draw with the tree nodes. The class is used as follows:

Private m_ctlTreeViewEx As TreeViewEx

Private Sub Form1_Load(ByVal sender As System.Object, _
            ByVal e As System.EventArgs) Handles MyBase.Load

   Dim objRootTreeNodeEx As TreeNodeEx

   m_ctlTreeViewEx = New TreeViewEx()
   m_ctlTreeViewEx.Left = 0
   m_ctlTreeViewEx.Top = 0
   m_ctlTreeViewEx.Dock = DockStyle.Fill

   objRootTreeNodeEx = AddNodeToTreeView(m_ctlTreeViewEx.Nodes, _
                       "This is the first node", 12, 5)

   AddNodeToTreeView(objRootTreeNodeEx.Nodes, "The second node", 4, 6)
   AddNodeToTreeView(objRootTreeNodeEx.Nodes, "Third node", 0, 5)
   AddNodeToTreeView(objRootTreeNodeEx.Nodes, "Node 4", 5, 1)
   AddNodeToTreeView(objRootTreeNodeEx.Nodes, "Last node", -1, 0)


End Sub

Points of Interest

There are some points of interest in the source code:

  • Windows Common Controls send NM_CUSTOMDRAW notifications through WM_NOTIFY messages to the parent window. So, we would need to intercept that message in the parent window, outside of our treeview control, which breaks the encapsulation rules. Fortunately, the .NET Framework allows controls to receive that message "reflected". To do this, the .NET Framework adds the value 0x2000 to the value of the WM_NOTIFY message and sends it to the control. Therefore, the TreeView control can receive the WM_NOTIFY message sent to its parent window using the following code in its own WndProc procedure:
    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
       Const WM_NOTIFY As Integer = &H4E
       Dim iResult As Integer
       Dim bHandled As Boolean = False
       If m.Msg = (&H2000 Or WM_NOTIFY) Then
       ' It is the reflected WM_NOTIFY message sent to the parent
          If m.WParam.Equals(Me.Handle) Then
             iResult = HandleNotify(m)
             m.Result = New IntPtr(iResult)
             bHandled = True
          End If
       End If
       If Not bHandled Then
       End If
    End Sub
  • To draw the text of a node, which mixes bold and non-bold portions, we need to draw the initial non-bold portion, the bold portion, and the final non-bold portion. To do this, we need to know the length of each portion in pixels, to set the coordinate X of the next portion, and we need a very accurate measure to avoid "holes" between two portions. It happens that when using the function Graphics.MeasureCharacterRanges to measure drawn strings, some pixels are added to the exact result. Since we need the exact result (in order to draw the next text just after the previous one), we can use the following trick: we measure the length of the text and the length of the text duplicated: since in both cases the extra pixels are added, the difference will be the exact length.


  • 24-May-2005. Initial version.


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

You may also be interested in...

Comments and Discussions

QuestionHow about custom drawn icons? Pin
Amit Gee7-Aug-05 15:23
memberAmit Gee7-Aug-05 15:23 
GeneralGreat article - and very timely Pin
Mark Mischke7-Jul-05 1:40
sussMark Mischke7-Jul-05 1:40 
Generalexcellent Pin
henok14-Jun-05 13:56
memberhenok14-Jun-05 13:56 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.171207.1 | Last Updated 26 May 2005
Article Copyright 2005 by Carlos J. Quintero
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid