Microsoft KB Archive/315934

= PRB: Windows Forms TreeView Control Does Not Handle State Image Lists in Visual Basic .NET =

Article ID: 315934

Article Last Modified on 3/24/2004

-

APPLIES TO


 * Microsoft .NET Framework 1.1
 * Microsoft .NET Framework 1.0
 * Microsoft Visual Basic .NET 2003 Standard Edition
 * Microsoft Visual Basic .NET 2002 Standard Edition

-



This article was previously published under Q315934



For a Microsoft Visual C# .NET version of this article, see 313134.



SYMPTOMS
The Windows Forms TreeView control displays a hierarchy of nodes that is similar to the way that Windows Explorer displays folders in the left pane. With the Windows Forms TreeView control, the application cannot use a State image list to display a State icon. The State icon appears to the left of the icon that is displayed for a node in the control. This behavior differs from the behavior of the underlying Win32 TreeView control.



RESOLUTION
The .NET Windows Forms application can use Interop services to direct the underlying Win32 TreeView control to display a State icon. To do this, the application can assign a value to each field in the TVITEM structure and send a TVM_SETITEM message to the underlying Win32 TreeView control through Interop services.



MORE INFORMATION
A Win32 TreeView control has two image lists that are associated with it:
 * Normal image list, which contains selected, nonselected, and overlay images for the items of a TreeView control.
 * State image list, which you can use to indicate application-defined item states. A State image is displayed to the left of an item's selected or nonselected image.

Because the Windows Forms TreeView control does not handle the State image list, follow these steps:
 * 1) Use Interop services to send a TVM_SETIMAGELIST message with the TVSIL_STATE flag to the underlying Win32 control to set the State image list.
 * 2) Send a TVM_SETITEM message to tell the control on which node to display a specific image from the image list. You must define the Win32 API function SendMessage to send these messages.

Because the TVM_SETIMAGELIST message and the TVM_SETITEM message require different parameters when they are sent to a TreeView control, you must overload the SendMessage function (as the following code shows).

This code demonstrates how to add a State image list to a Windows Forms TreeView control and how to display an image from the control on the root node.

Step-by-Step Example
 Start Microsoft Visual Studio .NET, and then create a new Windows Application using Visual Basic .NET. Form1 is added to the project by default. On Form1, add a TreeView, a Button, and an ImageList control. Their default names are TreeView1, Button1 and ImageList1 respectively. In the Properties of ImageList, click the ellipsis button (...)of the Images property, and then add at least two images. This is required for the sample to work.  In the code window of Form1.vb, add the following statement as the first line of code: 'Use Interop services Imports System.Runtime.InteropServices   Copy and paste the following code after the Inherits statement in Form1 class: Public Const TV_FIRST = 4352 Public Const TVSIL_NORMAL = 0 Public Const TVSIL_STATE = 2 Public Const TVM_SETIMAGELIST = TV_FIRST + 9 Public Const TVM_GETNEXTITEM = TV_FIRST + 10 Public Const TVIF_HANDLE = 16 Public Const TVIF_STATE = 8 Public Const TVIF_IMAGE = 2 Public Const TVIS_STATEIMAGEMASK = 61440 Public Const TVM_SETITEM = TV_FIRST + 13 Public Const TVGN_ROOT = 0

'Use a sequential structure layout to define TVITEM for the TreeView control.  _ Public Structure TVITEM Dim mask As Integer Dim hItem As IntPtr Dim state As Integer Dim stateMask As Integer Dim pszText As IntPtr Dim cchTextMax As Integer Dim iImage As Integer Dim iSelectedImage As Integer Dim cChildren As Integer Dim lParam As IntPtr End Structure

'Declare two overloaded SendMessage functions. The 'difference is in the last parameter: one is ByVal and the ' other one is ByRef. <DllImport(&quot;user32.dll&quot;)> _ Public Overloads Shared Function SendMessage _ (ByVal hWnd As IntPtr, ByVal Msg As Integer, _   ByVal wParam As Integer, ByVal lParam As Integer) As Integer End Function

<DllImport(&quot;User32.dll&quot;, CharSet:=CharSet.Auto)> _ Public Overloads Shared Function SendMessage _ (ByVal hWnd As IntPtr, ByVal msg As Integer, _   ByVal wParam As Integer, ByRef lParam As TVITEM) As Integer End Function </li>  In the Form1_Load event, copy and paste the following code: TreeView1.Nodes.Add(&quot;Node1&quot;) TreeView1.Nodes.Add(&quot;Node2&quot;) </li>  In the Button1_Click event, copy and paste the following code: Dim hWnd As IntPtr Dim hRoot As IntPtr Dim tvi As TVITEM Dim lRet As Integer

hWnd = TreeView1.Handle 'Send a TVM_SETIMAGELIST with TVSIL_STATE. lRet = SendMessage(hWnd, TVM_SETIMAGELIST, TVSIL_STATE, (ImageList1.Handle).ToInt32) 'Get a handle to the top row hRoot = IntPtr.op_Explicit(SendMessage(hWnd, TVM_GETNEXTITEM, TVGN_ROOT, 0)) 'The following uses the TVM_SETITEM message to set the state 'of a given item. It uses the TVITEM structure. 'tvi.mask: include TVIF_HANDLE and TVIF_STATE tvi.mask = TVIF_HANDLE Or TVIF_STATE 'To use the state image, tvi.state cannot be 0. 'Setting it to 1 means to use the second image in the image list. tvi.state = 1 'Left shift the bits by 12 to put information in bits 12 to 15. tvi.state = tvi.state * (2 ^ 12) 'Set stateMask. -This is required to isolate state above. tvi.stateMask = TVIS_STATEIMAGEMASK 'Set state for the root node. tvi.hItem = hRoot 'Initialize the rest to zero. tvi.pszText = IntPtr.op_Explicit(0) tvi.cchTextMax = 0 tvi.iImage = 0 tvi.iSelectedImage = 0 tvi.cChildren = 0 tvi.lParam = IntPtr.op_Explicit(0) 'Send the TVM_SETITEM message. lRet = SendMessage(hWnd, TVM_SETITEM, 0, tvi) </li> Press the F5 key to run the application. Click Button1 and notice that a state image is added to the root node.</li></ol>

Keywords: kbwindowsforms kbtreeview kbgdi kbprb kbctrl KB315934

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.