zhangjjwm

导航

Custom Draw TreeView in VB.NET

Introduction

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.

Background

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)
colNodes.Add(objTreeNodeEx)
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()
Me.Controls.Add(m_ctlTreeViewEx)
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)
objRootTreeNodeEx.Expand()
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
        MyBase.WndProc(m)
        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.

History

  • 24-May-2005. Initial version.

Carlos J. Quintero


Click here to view Carlos J. Quintero's online profile.

Download source - 7.92 Kb

posted on 2006-05-16 18:10  星空下的悠云  阅读(536)  评论(0编辑  收藏  举报