none
How to select an item in a TreeView, clicking in the button by hwnd api RRS feed

  • Question

  • How to select an item in a TreeView, clicking in the button In  program another by hwnd api Example explain how I am treating with treeview In  program another ?

     <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As Integer, ByVal lParam As String) As Integer
        End Function
        Private Const TVM_GETNEXTITEM As Integer = (TV_FIRST + 10)
        Private Const TVM_SELECTITEM As Integer = (TV_FIRST + 11)
        Public Const TV_FIRST As Integer = &H1100
        Public Const TVM_GETITEM = TV_FIRST + 12
        Public Const TVM_EXPAND As Integer = TV_FIRST + 2
        Public Const TVE_EXPAND As Integer = &H2
        Public Const TVM_GETITEMRECT As Integer = TV_FIRST + 4
        Public Const TVGN_CARET As Integer = &H9
        Public Const TVM_SORTCHILDRENCB As Integer = 4373
        Public Const TVM_GETEDITCONTROL = TV_FIRST + 15
        Public Const EM_LIMITTEXT = &HC5
        Structure TV_ITEM
            Public mask As Integer
            Public hItem As Integer
            Public State As Integer
            Public stateMask As Integer
            Public pszText As String
            Public cchTextMax As Integer
            Public iImage As Integer
            Public iSelectedImage As Integer
            Public cChildren As Integer
            Public lParam As Integer
        End Structure
        Private Const TVIF_TEXT As Integer = &H1
        Private Const TVGN_ROOT As Integer = &H0
        Private Const TVGN_NEXT As Integer = &H1
        Private Const TVGN_PREVIOUS As Integer = &H2
        'Const TVGN_PARENT = &H3
        Private Const TVGN_CHILD As Integer = &H4
        Private Const TVGN_FIRSTVISIBLE As Integer = &H5
        Private Const TVGN_NEXTVISIBLE As Integer = &H6
        Private Const TVGN_PREVIOUSVISIBLE As Integer = &H7
     Private Const TVGN_DROPHILITE As Integer = &H8
     Private Const BN_CLICKED As Integer = 245
    Private Const BM_CLICK As Integer = &HF5

    Saturday, August 30, 2014 9:52 PM

Answers

  • Hi,

     Below is an example of how you can select/expand a root node in a Treeview on a 3rd party window by the nodes index. You have to iterate through the nodes to get to the one you want and then use TVM_SELECTITEM and/or TVM_EXPAND. If you want to select a child node you will need to do somewhat the same thing except you would use TVGN_CHILD instead of the TVGN_NEXT. I left all the constants in the code in case you want to do other stuff too.

    Imports System.Runtime.InteropServices
    Imports System.Text
    
    Public Class Form1
        Private TVList As New List(Of IntPtr)
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim hParent As IntPtr = FindWindowW(Nothing, "form1") 'Get the handle of the Parent Window that the TreeView is on
            If hParent <> IntPtr.Zero Then
                Dim hTv As IntPtr = GetTreeviewHandlesFrom(hParent)(0) 'Get the handle of the 1st Treeview on the Parent Window
                If hTv <> IntPtr.Zero Then
                    Dim hRootNode As IntPtr = GetRootNodeHandle(hTv, 2) 'Get the handle of the 3rd root node (2)
                    If hRootNode <> IntPtr.Zero Then
                        SendMessage(hTv, TVM_EXPAND, TVE_EXPAND, hRootNode) 'Expand the node
                        SendMessage(hTv, TVM_SELECTITEM, TVGN_CARET, hRootNode) 'Select the node
                    End If
                End If
            End If
        End Sub
    
        Private Function GetRootNodeHandle(ByVal tvHandle As IntPtr, ByVal NodeIndex As Integer) As IntPtr
            Dim hNode As IntPtr = SendMessage(tvHandle, TVM_GETNEXTITEM, TVGN_ROOT, IntPtr.Zero) 'Get 1st root node handle
            'Iterate to the node wanted if (NodeIndex) is not not the 1st node (0) and get its handle
            For i As Integer = 1 To NodeIndex
                hNode = SendMessage(tvHandle, TVM_GETNEXTITEM, TVGN_NEXT, hNode)
            Next
            Return hNode 'Return the root node handle
        End Function
    
        Private Function GetTreeviewHandlesFrom(ByVal hwnd As IntPtr) As IntPtr()
            TVList.Clear()
            EnumChildWindows(hwnd, AddressOf EnumChildWindowProc, 0)
            Return TVList.ToArray
        End Function
    
        Private Function EnumChildWindowProc(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Integer
            Dim cn As New StringBuilder(255)
            GetClassNameW(hwnd, cn, 255)
            If cn.ToString.ToLower.ToLower.Contains("systreeview32") Then 'Make sure the child window is a Treeview before adding its handle to the List
                TVList.Add(hwnd)
            End If
            Return 1
        End Function
    
        <DllImport("user32.dll", EntryPoint:="FindWindowW")> _
        Private Shared Function FindWindowW(<MarshalAs(UnmanagedType.LPTStr)> ByVal lpClassName As String, <MarshalAs(UnmanagedType.LPTStr)> ByVal lpWindowName As String) As IntPtr
        End Function
    
        <DllImport("user32.dll", EntryPoint:="SendMessageW")> _
        Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As Integer, ByVal lParam As IntPtr) As IntPtr
        End Function
    
        <DllImport("user32.dll", EntryPoint:="GetClassNameW")> _
        Private Shared Function GetClassNameW(ByVal hWnd As IntPtr, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpClassName As System.Text.StringBuilder, ByVal nMaxCount As Integer) As Integer
        End Function
    
        <UnmanagedFunctionPointer(CallingConvention.StdCall)> _
        Private Delegate Function EnumCallBackDelegate(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Integer
    
        <DllImport("user32.dll", EntryPoint:="EnumChildWindows")> _
        Private Shared Function EnumChildWindows(ByVal hWndParent As IntPtr, ByVal lpEnumFunc As EnumCallBackDelegate, ByVal lParam As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <StructLayout(LayoutKind.Sequential)> _
            Private Structure TVITEM
            Public mask As Integer
            Public hItem As IntPtr
            Public State As Integer
            Public stateMask As Integer
            Public pszText As IntPtr
            Public cchTextMax As Integer
            Public iImage As Integer
            Public iSelectedImage As Integer
            Public cChildren As Integer
            Public lParam As IntPtr
        End Structure
    
        Private Const TV_FIRST As Integer = &H1100
        Private Const TVM_EXPAND As Integer = (TV_FIRST + 2)
        Private Const TVM_GETITEMRECT As Integer = (TV_FIRST + 4)
        Private Const TVM_GETCOUNT As Integer = (TV_FIRST + 5)
        Private Const TVM_GETNEXTITEM As Integer = (TV_FIRST + 10)
        Private Const TVM_SELECTITEM As Integer = (TV_FIRST + 11)
        Private Const TVM_HITTEST As Integer = (TV_FIRST + 17)
        Private Const TVM_ENSUREVISIBLE As Integer = (TV_FIRST + 20)
        Private Const TVM_ENDEDITLABELNOW As Integer = (TV_FIRST + 22)
        Private Const TVM_GETTOOLTIPS As Integer = (TV_FIRST + 25)
        Private Const TVM_GETITEMSTATE As Integer = (TV_FIRST + 39)
        Private Const TVM_MAPACCIDTOHTREEITEM As Integer = (TV_FIRST + 42)
        Private Const TVM_MAPHTREEITEMTOACCID As Integer = (TV_FIRST + 43)
        Private Const TVM_GETITEMW As Integer = (TV_FIRST + 62)
        Private Const TVM_SETITEMW As Integer = (TV_FIRST + 63)
        Private Const TVM_EDITLABELW As Integer = (TV_FIRST + 65)
    
        Private Const TVGN_ROOT As Integer = &H0
        Private Const TVGN_NEXT As Integer = &H1
        Private Const TVGN_PREVIOUS As Integer = &H2
        Private Const TVGN_PARENT As Integer = &H3
        Private Const TVGN_CHILD As Integer = &H4
        Private Const TVGN_CARET As Integer = &H9
    
        Private Const TVE_COLLAPSE As Integer = &H1
        Private Const TVE_EXPAND As Integer = &H2
    
        Private Const TVIF_TEXT As Integer = &H1
        Private Const TVIF_IMAGE As Integer = &H2
        Private Const TVIF_STATE As Integer = &H8
        Private Const TVIF_CHILDREN As Integer = &H40
    
        Private Const TVIS_SELECTED As Integer = &H2
        Private Const TVIS_EXPANDED As Integer = &H20
        Private Const TVIS_STATEIMAGEMASK As Integer = &HF000
    End Class
    
    


    If you say it can`t be done then i`ll try it

    • Marked as answer by HeroCodec Sunday, August 31, 2014 11:13 AM
    Sunday, August 31, 2014 12:59 AM
  • Hi,

     Doing this is kind of similar to getting the items rectangle area. You need to read and write to the processes`s memory to retrieve the text of each node using the TVITEM structure. Here is an example of getting each child nodes text of the 3rd root node.

    Imports System.Runtime.InteropServices
    Imports System.Text
    
    Public Class Form1
        Private TVList As New List(Of IntPtr)
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim hParent As IntPtr = FindWindowW(Nothing, "form1") 'Get the handle of the Parent Window that the TreeView is on
            If hParent <> IntPtr.Zero Then
                Dim hTv As IntPtr = GetTreeviewHandlesFrom(hParent)(0) 'Get the handle of the 1st Treeview on the Parent Window
                If hTv <> IntPtr.Zero Then
                    Dim hRootNode As IntPtr = GetRootNodeHandle(hTv, 2) 'Get the handle of the 3rd root node (2)
                    If hRootNode <> IntPtr.Zero Then
                        'Call the GetAllChildNodeText function which returns a string array of all the child
                        'nodes texts and assing the array to the lines property of the textbox
                        TextBox1.Lines = GetAllChildNodeText(hTv, hRootNode)
                    End If
                End If
            End If
        End Sub
    
        Private Function GetAllChildNodeText(ByVal tvHandle As IntPtr, ByVal hParentNode As IntPtr) As String()
            Dim MemTextPointer, MemTVItemPointer, TextPointer, TVItemPointer As IntPtr
            Dim nTxt As New List(Of String)
            Dim NodeText As String
            Dim NodeTextLength As Integer
            Dim hChildNode As IntPtr = SendMessageW(tvHandle, TVM_GETNEXTITEM, TVGN_CHILD, hParentNode)
    
            Dim procId As Integer = Nothing
            GetWindowThreadProcessId(tvHandle, procId)
            Dim hProc As IntPtr = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, False, procId)
    
            While hChildNode <> IntPtr.Zero
                NodeText = Space(256)
                NodeTextLength = NodeText.Length
    
                TextPointer = Marshal.StringToHGlobalUni(NodeText)
                MemTextPointer = VirtualAllocEx(hProc, IntPtr.Zero, NodeTextLength, MEM_COMMIT, PAGE_READWRITE)
                WriteProcessMemory(hProc, MemTextPointer, TextPointer, NodeTextLength, 0)
    
                Dim tvi As TVITEM
                tvi.mask = TVIF_TEXT
                tvi.hItem = hChildNode
                tvi.pszText = MemTextPointer
                tvi.cchTextMax = NodeTextLength
                Dim nSizeTVITEM As Integer = Marshal.SizeOf(tvi)
                MemTVItemPointer = VirtualAllocEx(hProc, IntPtr.Zero, nSizeTVITEM, MEM_COMMIT, PAGE_READWRITE)
                TVItemPointer = Marshal.AllocHGlobal(nSizeTVITEM)
                Marshal.StructureToPtr(tvi, TVItemPointer, True)
                WriteProcessMemory(hProc, MemTVItemPointer, TVItemPointer, nSizeTVITEM, 0)
    
                SendMessageW(tvHandle, TVM_GETITEMW, 0, MemTVItemPointer)
    
                ReadProcessMemory(hProc, MemTextPointer, TextPointer, NodeTextLength, 0)
                NodeText = Marshal.PtrToStringUni(TextPointer)
                nTxt.Add(NodeText)
    
                Marshal.FreeHGlobal(TVItemPointer)
    
                hChildNode = SendMessageW(tvHandle, TVM_GETNEXTITEM, TVGN_NEXT, hChildNode)
            End While
    
            VirtualFreeEx(hProc, MemTVItemPointer, 0, MEM_RELEASE)
            VirtualFreeEx(hProc, MemTextPointer, 0, MEM_RELEASE)
            CloseHandle(hProc)
    
            Return nTxt.ToArray
        End Function
    
        Private Function GetRootNodeHandle(ByVal tvHandle As IntPtr, ByVal NodeIndex As Integer) As IntPtr
            Dim hNode As IntPtr = SendMessageW(tvHandle, TVM_GETNEXTITEM, TVGN_ROOT, IntPtr.Zero) 'Get 1st root node handle
            'Iterate to the node wanted if (NodeIndex) is not not the 1st node (0) and get its handle
            For i As Integer = 1 To NodeIndex
                hNode = SendMessageW(tvHandle, TVM_GETNEXTITEM, TVGN_NEXT, hNode)
            Next
            Return hNode 'Return the root node handle
        End Function
    
        Private Function GetChildNodeHandle(ByVal tvHandle As IntPtr, ByVal hParentNode As IntPtr, ByVal ChildNodeIndex As Integer) As IntPtr
            Dim hChildNode As IntPtr = SendMessageW(tvHandle, TVM_GETNEXTITEM, TVGN_CHILD, hParentNode) 'Get the 1st child node
            'Iterate to the child node wanted if (ChildNodeIndex) is not not the 1st node (0) and get its handle
            For i As Integer = 1 To ChildNodeIndex
                hChildNode = SendMessageW(tvHandle, TVM_GETNEXTITEM, TVGN_NEXT, hChildNode)
            Next
            Return hChildNode 'Return the child node handle
        End Function
    
        Private Function GetTreeviewHandlesFrom(ByVal hwnd As IntPtr) As List(Of IntPtr)
            TVList.Clear()
            EnumChildWindows(hwnd, AddressOf EnumChildWindowProc, 0)
            Return TVList
        End Function
    
        Private Function EnumChildWindowProc(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Integer
            Dim cn As New StringBuilder(255)
            GetClassNameW(hwnd, cn, 255)
            If cn.ToString.ToLower.ToLower.Contains("systreeview32") Then 'Make sure the child window is a Treeview before adding its handle to the List
                TVList.Add(hwnd)
            End If
            Return 1
        End Function
    
        <DllImport("kernel32.dll", EntryPoint:="WriteProcessMemory")> _
        Private Shared Function WriteProcessMemory(ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByVal lpBuffer As IntPtr, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("kernel32.dll", EntryPoint:="ReadProcessMemory")> _
        Private Shared Function ReadProcessMemory(ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByVal lpBuffer As IntPtr, ByVal nSize As Integer, ByRef lpNumberOfBytesRead As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("kernel32.dll", EntryPoint:="OpenProcess")> _
        Private Shared Function OpenProcess(ByVal dwDesiredAccess As UInteger, <MarshalAs(UnmanagedType.Bool)> ByVal bInheritHandle As Boolean, ByVal dwProcessId As Integer) As IntPtr
        End Function
    
        <DllImport("kernel32.dll", EntryPoint:="CloseHandle")> _
        Private Shared Function CloseHandle(ByVal hObject As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("kernel32.dll", EntryPoint:="VirtualAllocEx")> _
        Private Shared Function VirtualAllocEx(ByVal hProcess As IntPtr, ByVal lpAddress As IntPtr, ByVal dwSize As Integer, ByVal flAllocationType As UInteger, ByVal flProtect As UInteger) As IntPtr
        End Function
    
        <DllImportAttribute("kernel32.dll", EntryPoint:="VirtualFreeEx")> _
        Private Shared Function VirtualFreeEx(ByVal hProcess As IntPtr, ByVal lpAddress As IntPtr, ByVal dwSize As UInteger, ByVal dwFreeType As UInteger) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("user32.dll", EntryPoint:="FindWindowW")> _
        Private Shared Function FindWindowW(<MarshalAs(UnmanagedType.LPTStr)> ByVal lpClassName As String, <MarshalAs(UnmanagedType.LPTStr)> ByVal lpWindowName As String) As IntPtr
        End Function
    
        <DllImport("user32.dll", EntryPoint:="GetClassNameW")> _
        Private Shared Function GetClassNameW(ByVal hWnd As IntPtr, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpClassName As System.Text.StringBuilder, ByVal nMaxCount As Integer) As Integer
        End Function
    
        <UnmanagedFunctionPointer(CallingConvention.StdCall)> _
        Private Delegate Function EnumCallBackDelegate(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Integer
    
        <DllImport("user32.dll", EntryPoint:="EnumChildWindows")> _
        Private Shared Function EnumChildWindows(ByVal hWndParent As IntPtr, ByVal lpEnumFunc As EnumCallBackDelegate, ByVal lParam As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("user32.dll", EntryPoint:="GetWindowThreadProcessId")> _
        Private Shared Function GetWindowThreadProcessId(ByVal hWnd As IntPtr, ByRef lpdwProcessId As Integer) As Integer
        End Function
    
        <DllImport("user32.dll", EntryPoint:="SendMessageW")> _
        Private Shared Function SendMessageW(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As Integer, ByVal lParam As IntPtr) As IntPtr
        End Function
    
        <StructLayout(LayoutKind.Sequential)> _
            Private Structure TVITEM
            Public mask As Integer
            Public hItem As IntPtr
            Public State As Integer
            Public stateMask As Integer
            Public pszText As IntPtr
            Public cchTextMax As Integer
            Public iImage As Integer
            Public iSelectedImage As Integer
            Public cChildren As Integer
            Public lParam As IntPtr
        End Structure
    
        Private Const TV_FIRST As Integer = &H1100
        Private Const TVM_EXPAND As Integer = (TV_FIRST + 2)
        Private Const TVM_GETITEMRECT As Integer = (TV_FIRST + 4)
        Private Const TVM_GETCOUNT As Integer = (TV_FIRST + 5)
        Private Const TVM_GETNEXTITEM As Integer = (TV_FIRST + 10)
        Private Const TVM_SELECTITEM As Integer = (TV_FIRST + 11)
        Private Const TVM_HITTEST As Integer = (TV_FIRST + 17)
        Private Const TVM_ENSUREVISIBLE As Integer = (TV_FIRST + 20)
        Private Const TVM_ENDEDITLABELNOW As Integer = (TV_FIRST + 22)
        Private Const TVM_GETTOOLTIPS As Integer = (TV_FIRST + 25)
        Private Const TVM_GETITEMSTATE As Integer = (TV_FIRST + 39)
        Private Const TVM_MAPACCIDTOHTREEITEM As Integer = (TV_FIRST + 42)
        Private Const TVM_MAPHTREEITEMTOACCID As Integer = (TV_FIRST + 43)
        Private Const TVM_GETITEMW As Integer = (TV_FIRST + 62)
        Private Const TVM_SETITEMW As Integer = (TV_FIRST + 63)
        Private Const TVM_EDITLABELW As Integer = (TV_FIRST + 65)
    
        Private Const TVGN_ROOT As Integer = &H0
        Private Const TVGN_NEXT As Integer = &H1
        Private Const TVGN_PREVIOUS As Integer = &H2
        Private Const TVGN_PARENT As Integer = &H3
        Private Const TVGN_CHILD As Integer = &H4
        Private Const TVGN_CARET As Integer = &H9
    
        Private Const TVE_COLLAPSE As Integer = &H1
        Private Const TVE_EXPAND As Integer = &H2
    
        Private Const TVIF_TEXT As Integer = &H1
        Private Const TVIF_IMAGE As Integer = &H2
        Private Const TVIF_STATE As Integer = &H8
        Private Const TVIF_CHILDREN As Integer = &H40
    
        Private Const TVIS_SELECTED As Integer = &H2
        Private Const TVIS_EXPANDED As Integer = &H20
        Private Const TVIS_STATEIMAGEMASK As Integer = &HF000
    
        Private Const MEM_COMMIT As UInteger = &H1000
        Private Const MEM_RELEASE As UInteger = &H8000
        Private Const PAGE_READWRITE As UInteger = &H4
    
        Private Const PROCESS_VM_READ As UInteger = &H10
        Private Const PROCESS_VM_WRITE As UInteger = &H20
        Private Const PROCESS_VM_OPERATION As UInteger = &H8
    End Class
    
    
     

     

     You will need to study all these examples i have written for you and do some experimenting so you can start figuring this stuff out. You can get a lot of information from the msdn documents on these Functions and Structures and by searching the internet for examples. I know there is not a lot of examples and the msdn documents can be confusing or missing info because, that is how i learned to do these things but, nothing is easy until you learn it.   8)


    If you say it can`t be done then i`ll try it

    • Marked as answer by HeroCodec Wednesday, September 3, 2014 3:38 PM
    Wednesday, September 3, 2014 3:10 PM
  • Well, as i said, you will need to get the rectangle area of the node and then move the mouse to that rectangle area of the screen and then simulate a mouse click. The treeview node will need to be visible on the screen in order for it to be clicked other wise this method will not work.

     In the code below i have added another Sub and a bunch more API functions, constants, and the RECT structure. The Sub is called ClickNodeWithMouse. You will need to find the node handle as has been done in the prior examples and then you can call the ClickNodeWithMouse sub to click the mouse on it. I did not know if you wanted to make a single or double left click or maybe a right click so i made the sub with a few parameters that you can set to make it do whatever you need.

     The example below finds the handle to the 2nd child node of the 3rd root node and then double clicks the left mouse button on it. Then it returns the cursor to the position it was at when the sub was called. In this case it returns it back over the button on my form that i click to make all this happen. It should be quick enough that you will not really notice the cursor moving. You can also set the ReturnMousePosition parameter of the Sub to false so that the mouse is left over the node if you want to do that.

    Imports System.Runtime.InteropServices
    Imports System.Text
    
    Public Class Form1
        Private TVList As New List(Of IntPtr)
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim hParent As IntPtr = FindWindowW(Nothing, "form1") 'Get the handle of the Parent Window that the TreeView is on
            If hParent <> IntPtr.Zero Then
                Dim hTv As IntPtr = GetTreeviewHandlesFrom(hParent)(0) 'Get the handle of the 1st Treeview on the Parent Window
                If hTv <> IntPtr.Zero Then
                    Dim hRootNode As IntPtr = GetRootNodeHandle(hTv, 2) 'Get the handle of the 3rd root node (2)
                    If hRootNode <> IntPtr.Zero Then
                        SendMessageW(hTv, TVM_EXPAND, TVE_EXPAND, hRootNode) 'Expand the root node
                        Dim hChildNode As IntPtr = GetChildNodeHandle(hTv, hRootNode, 1) 'Get the handle of the 2nd child node (1)
                        If hChildNode <> IntPtr.Zero Then
                            'SendMessageW(hTv, TVM_EXPAND, TVE_EXPAND, hChildNode) 'Expand the child node
                            'SendMessageW(hTv, TVM_SELECTITEM, TVGN_CARET, hChildNode) 'Select the childnode
    
                            'moves the cursor to the node, double clicks the left mouse button, and then returns the cursor to its original position
                            ClickNodeWithMouse(hTv, hChildNode, False, True, True)
                        End If
                    End If
                End If
            End If
        End Sub
    
        Private Function GetRootNodeHandle(ByVal tvHandle As IntPtr, ByVal NodeIndex As Integer) As IntPtr
            Dim hNode As IntPtr = SendMessageW(tvHandle, TVM_GETNEXTITEM, TVGN_ROOT, IntPtr.Zero) 'Get 1st root node handle
            'Iterate to the node wanted if (NodeIndex) is not not the 1st node (0) and get its handle
            For i As Integer = 1 To NodeIndex
                hNode = SendMessageW(tvHandle, TVM_GETNEXTITEM, TVGN_NEXT, hNode)
            Next
            Return hNode 'Return the root node handle
        End Function
    
        Private Function GetChildNodeHandle(ByVal tvHandle As IntPtr, ByVal hParentNode As IntPtr, ByVal ChildNodeIndex As Integer) As IntPtr
            Dim hChildNode As IntPtr = SendMessageW(tvHandle, TVM_GETNEXTITEM, TVGN_CHILD, hParentNode) 'Get the 1st child node
            'Iterate to the child node wanted if (ChildNodeIndex) is not not the 1st node (0) and get its handle
            For i As Integer = 1 To ChildNodeIndex
                hChildNode = SendMessageW(tvHandle, TVM_GETNEXTITEM, TVGN_NEXT, hChildNode)
            Next
            Return hChildNode 'Return the child node handle
        End Function
    
        ''' <summary>Moves the cursor to the node and clicks the mouse button.</summary>
        ''' <param name="tvHandle">Handle to the treeview control</param>
        ''' <param name="hNode">Handle to the treeview node to click</param>
        ''' <param name="RightClick">True to Right click the mouse. False to Left click the mouse.</param>
        ''' <param name="DoubleClick">True to double click the mouse button (only for left click).</param>
        ''' <param name="ReturnMousePosition">True to return the mouse cursor to its original position after clicking</param>
        Private Sub ClickNodeWithMouse(ByVal tvHandle As IntPtr, ByVal hNode As IntPtr, ByVal RightClick As Boolean, ByVal DoubleClick As Boolean, ByVal ReturnMousePosition As Boolean)
            Dim procId As Integer = Nothing
            GetWindowThreadProcessId(tvHandle, procId)
            Dim hProc As IntPtr = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, False, procId)
    
            Dim nRect As New RECT
            nRect.left = hNode.ToInt32
    
            Dim tvNodeRectPtr As IntPtr = VirtualAllocEx(hProc, IntPtr.Zero, Marshal.SizeOf(nRect), MEM_COMMIT, PAGE_READWRITE)
            WriteProcessMemory(hProc, tvNodeRectPtr, nRect, Marshal.SizeOf(nRect), 0)
    
            SendMessageW(tvHandle, TVM_GETITEMRECT, 1, tvNodeRectPtr)
    
            ReadProcessMemory(hProc, tvNodeRectPtr, nRect, Marshal.SizeOf(nRect), 0)
    
            VirtualFreeEx(hProc, tvNodeRectPtr, 0, MEM_RELEASE)
            CloseHandle(hProc)
    
            Dim tvRect As New RECT
            GetWindowRect(tvHandle, tvRect)
    
            Dim CurrentCursorPosition As Point = Cursor.Position
    
            Cursor.Position = New Point(tvRect.left + nRect.left + 20, tvRect.top + nRect.top + CInt((nRect.bottom - nRect.top) / 2))
            If RightClick Then
                mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0)
                mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0)
            Else
                mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
                mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)
                If DoubleClick Then
                    mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
                    mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)
                End If
            End If
    
            If ReturnMousePosition Then
                Cursor.Position = CurrentCursorPosition
            End If
        End Sub
    
        Private Function GetTreeviewHandlesFrom(ByVal hwnd As IntPtr) As IntPtr()
            TVList.Clear()
            EnumChildWindows(hwnd, AddressOf EnumChildWindowProc, 0)
            Return TVList.ToArray
        End Function
    
        Private Function EnumChildWindowProc(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Integer
            Dim cn As New StringBuilder(255)
            GetClassNameW(hwnd, cn, 255)
            If cn.ToString.ToLower.ToLower.Contains("systreeview32") Then 'Make sure the child window is a Treeview before adding its handle to the List
                TVList.Add(hwnd)
            End If
            Return 1
        End Function
    
        <DllImport("user32.dll", EntryPoint:="FindWindowW")> _
        Private Shared Function FindWindowW(<MarshalAs(UnmanagedType.LPTStr)> ByVal lpClassName As String, <MarshalAs(UnmanagedType.LPTStr)> ByVal lpWindowName As String) As IntPtr
        End Function
    
        <DllImport("user32.dll", EntryPoint:="SendMessageW")> _
        Private Shared Function SendMessageW(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As Integer, ByVal lParam As IntPtr) As IntPtr
        End Function
    
        <DllImport("user32.dll", EntryPoint:="GetClassNameW")> _
        Private Shared Function GetClassNameW(ByVal hWnd As IntPtr, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpClassName As System.Text.StringBuilder, ByVal nMaxCount As Integer) As Integer
        End Function
    
        <UnmanagedFunctionPointer(CallingConvention.StdCall)> _
        Private Delegate Function EnumCallBackDelegate(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Integer
    
        <DllImport("user32.dll", EntryPoint:="EnumChildWindows")> _
        Private Shared Function EnumChildWindows(ByVal hWndParent As IntPtr, ByVal lpEnumFunc As EnumCallBackDelegate, ByVal lParam As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("kernel32.dll", EntryPoint:="WriteProcessMemory")> _
        Private Shared Function WriteProcessMemory(ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByRef lpBuffer As RECT, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("kernel32.dll", EntryPoint:="ReadProcessMemory")> _
        Private Shared Function ReadProcessMemory(ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByRef lpBuffer As RECT, ByVal nSize As Integer, ByRef lpNumberOfBytesRead As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("kernel32.dll", EntryPoint:="OpenProcess")> _
        Private Shared Function OpenProcess(ByVal dwDesiredAccess As UInteger, <MarshalAs(UnmanagedType.Bool)> ByVal bInheritHandle As Boolean, ByVal dwProcessId As Integer) As IntPtr
        End Function
    
        <DllImport("kernel32.dll", EntryPoint:="CloseHandle")> _
        Private Shared Function CloseHandle(ByVal hObject As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("kernel32.dll", EntryPoint:="VirtualAllocEx")> _
        Private Shared Function VirtualAllocEx(ByVal hProcess As IntPtr, ByVal lpAddress As IntPtr, ByVal dwSize As Integer, ByVal flAllocationType As UInteger, ByVal flProtect As UInteger) As IntPtr
        End Function
    
        <DllImportAttribute("kernel32.dll", EntryPoint:="VirtualFreeEx")> _
        Private Shared Function VirtualFreeEx(ByVal hProcess As IntPtr, ByVal lpAddress As IntPtr, ByVal dwSize As UInteger, ByVal dwFreeType As UInteger) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("user32.dll", EntryPoint:="GetWindowThreadProcessId")> _
        Private Shared Function GetWindowThreadProcessId(ByVal hWnd As IntPtr, ByRef lpdwProcessId As Integer) As Integer
        End Function
    
        <DllImport("user32.dll", EntryPoint:="GetWindowRect")> _
        Private Shared Function GetWindowRect(ByVal hWnd As IntPtr, ByRef lpRect As RECT) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("user32.dll", EntryPoint:="mouse_event")> _
        Private Shared Sub mouse_event(ByVal dwFlags As UInteger, ByVal dx As Integer, ByVal dy As Integer, ByVal dwData As Integer, ByVal dwExtraInfo As UInteger)
        End Sub
    
        <StructLayout(LayoutKind.Sequential)> _
        Private Structure RECT
            Public left As Integer
            Public top As Integer
            Public right As Integer
            Public bottom As Integer
        End Structure
    
        <StructLayout(LayoutKind.Sequential)> _
            Private Structure TVITEM
            Public mask As Integer
            Public hItem As IntPtr
            Public State As Integer
            Public stateMask As Integer
            Public pszText As IntPtr
            Public cchTextMax As Integer
            Public iImage As Integer
            Public iSelectedImage As Integer
            Public cChildren As Integer
            Public lParam As IntPtr
        End Structure
    
        Private Const TV_FIRST As Integer = &H1100
        Private Const TVM_EXPAND As Integer = (TV_FIRST + 2)
        Private Const TVM_GETITEMRECT As Integer = (TV_FIRST + 4)
        Private Const TVM_GETCOUNT As Integer = (TV_FIRST + 5)
        Private Const TVM_GETNEXTITEM As Integer = (TV_FIRST + 10)
        Private Const TVM_SELECTITEM As Integer = (TV_FIRST + 11)
        Private Const TVM_HITTEST As Integer = (TV_FIRST + 17)
        Private Const TVM_ENSUREVISIBLE As Integer = (TV_FIRST + 20)
        Private Const TVM_ENDEDITLABELNOW As Integer = (TV_FIRST + 22)
        Private Const TVM_GETTOOLTIPS As Integer = (TV_FIRST + 25)
        Private Const TVM_GETITEMSTATE As Integer = (TV_FIRST + 39)
        Private Const TVM_MAPACCIDTOHTREEITEM As Integer = (TV_FIRST + 42)
        Private Const TVM_MAPHTREEITEMTOACCID As Integer = (TV_FIRST + 43)
        Private Const TVM_GETITEMW As Integer = (TV_FIRST + 62)
        Private Const TVM_SETITEMW As Integer = (TV_FIRST + 63)
        Private Const TVM_EDITLABELW As Integer = (TV_FIRST + 65)
    
        Private Const TVGN_ROOT As Integer = &H0
        Private Const TVGN_NEXT As Integer = &H1
        Private Const TVGN_PREVIOUS As Integer = &H2
        Private Const TVGN_PARENT As Integer = &H3
        Private Const TVGN_CHILD As Integer = &H4
        Private Const TVGN_CARET As Integer = &H9
    
        Private Const TVE_COLLAPSE As Integer = &H1
        Private Const TVE_EXPAND As Integer = &H2
    
        Private Const TVIF_TEXT As Integer = &H1
        Private Const TVIF_IMAGE As Integer = &H2
        Private Const TVIF_STATE As Integer = &H8
        Private Const TVIF_CHILDREN As Integer = &H40
    
        Private Const TVIS_SELECTED As Integer = &H2
        Private Const TVIS_EXPANDED As Integer = &H20
        Private Const TVIS_STATEIMAGEMASK As Integer = &HF000
    
        Private Const MEM_COMMIT As UInteger = &H1000
        Private Const MEM_RELEASE As UInteger = &H8000
        Private Const PAGE_READWRITE As UInteger = &H4
    
        Private Const PROCESS_VM_READ As UInteger = &H10
        Private Const PROCESS_VM_WRITE As UInteger = &H20
        Private Const PROCESS_VM_OPERATION As UInteger = &H8
    
        Private Const MOUSEEVENTF_LEFTDOWN As Integer = &H2
        Private Const MOUSEEVENTF_LEFTUP As Integer = &H4
        Private Const MOUSEEVENTF_RIGHTDOWN As Integer = &H8
        Private Const MOUSEEVENTF_RIGHTUP As Integer = &H10
    
    End Class
    
    

     Here is the above example showing that it expands the nodes so that the 2nd child node of the 3rd root node is visible and then double clicks the left mouse button on it which expands the child node. Then it returns the mouse back to the button on my form. Then when i click the button a second time it does the same thing except it closes the child node when it is double clicked this time.

     

     This does seem like a lot of work just to click on a node in a 3rd party window. Perhaps it would be easier to just manually click it instead of going through all of this.  8)


    If you say it can`t be done then i`ll try it

    • Marked as answer by HeroCodec Sunday, August 31, 2014 11:00 PM
    Sunday, August 31, 2014 9:50 PM

All replies

  • Hi,

     Below is an example of how you can select/expand a root node in a Treeview on a 3rd party window by the nodes index. You have to iterate through the nodes to get to the one you want and then use TVM_SELECTITEM and/or TVM_EXPAND. If you want to select a child node you will need to do somewhat the same thing except you would use TVGN_CHILD instead of the TVGN_NEXT. I left all the constants in the code in case you want to do other stuff too.

    Imports System.Runtime.InteropServices
    Imports System.Text
    
    Public Class Form1
        Private TVList As New List(Of IntPtr)
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim hParent As IntPtr = FindWindowW(Nothing, "form1") 'Get the handle of the Parent Window that the TreeView is on
            If hParent <> IntPtr.Zero Then
                Dim hTv As IntPtr = GetTreeviewHandlesFrom(hParent)(0) 'Get the handle of the 1st Treeview on the Parent Window
                If hTv <> IntPtr.Zero Then
                    Dim hRootNode As IntPtr = GetRootNodeHandle(hTv, 2) 'Get the handle of the 3rd root node (2)
                    If hRootNode <> IntPtr.Zero Then
                        SendMessage(hTv, TVM_EXPAND, TVE_EXPAND, hRootNode) 'Expand the node
                        SendMessage(hTv, TVM_SELECTITEM, TVGN_CARET, hRootNode) 'Select the node
                    End If
                End If
            End If
        End Sub
    
        Private Function GetRootNodeHandle(ByVal tvHandle As IntPtr, ByVal NodeIndex As Integer) As IntPtr
            Dim hNode As IntPtr = SendMessage(tvHandle, TVM_GETNEXTITEM, TVGN_ROOT, IntPtr.Zero) 'Get 1st root node handle
            'Iterate to the node wanted if (NodeIndex) is not not the 1st node (0) and get its handle
            For i As Integer = 1 To NodeIndex
                hNode = SendMessage(tvHandle, TVM_GETNEXTITEM, TVGN_NEXT, hNode)
            Next
            Return hNode 'Return the root node handle
        End Function
    
        Private Function GetTreeviewHandlesFrom(ByVal hwnd As IntPtr) As IntPtr()
            TVList.Clear()
            EnumChildWindows(hwnd, AddressOf EnumChildWindowProc, 0)
            Return TVList.ToArray
        End Function
    
        Private Function EnumChildWindowProc(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Integer
            Dim cn As New StringBuilder(255)
            GetClassNameW(hwnd, cn, 255)
            If cn.ToString.ToLower.ToLower.Contains("systreeview32") Then 'Make sure the child window is a Treeview before adding its handle to the List
                TVList.Add(hwnd)
            End If
            Return 1
        End Function
    
        <DllImport("user32.dll", EntryPoint:="FindWindowW")> _
        Private Shared Function FindWindowW(<MarshalAs(UnmanagedType.LPTStr)> ByVal lpClassName As String, <MarshalAs(UnmanagedType.LPTStr)> ByVal lpWindowName As String) As IntPtr
        End Function
    
        <DllImport("user32.dll", EntryPoint:="SendMessageW")> _
        Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As Integer, ByVal lParam As IntPtr) As IntPtr
        End Function
    
        <DllImport("user32.dll", EntryPoint:="GetClassNameW")> _
        Private Shared Function GetClassNameW(ByVal hWnd As IntPtr, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpClassName As System.Text.StringBuilder, ByVal nMaxCount As Integer) As Integer
        End Function
    
        <UnmanagedFunctionPointer(CallingConvention.StdCall)> _
        Private Delegate Function EnumCallBackDelegate(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Integer
    
        <DllImport("user32.dll", EntryPoint:="EnumChildWindows")> _
        Private Shared Function EnumChildWindows(ByVal hWndParent As IntPtr, ByVal lpEnumFunc As EnumCallBackDelegate, ByVal lParam As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <StructLayout(LayoutKind.Sequential)> _
            Private Structure TVITEM
            Public mask As Integer
            Public hItem As IntPtr
            Public State As Integer
            Public stateMask As Integer
            Public pszText As IntPtr
            Public cchTextMax As Integer
            Public iImage As Integer
            Public iSelectedImage As Integer
            Public cChildren As Integer
            Public lParam As IntPtr
        End Structure
    
        Private Const TV_FIRST As Integer = &H1100
        Private Const TVM_EXPAND As Integer = (TV_FIRST + 2)
        Private Const TVM_GETITEMRECT As Integer = (TV_FIRST + 4)
        Private Const TVM_GETCOUNT As Integer = (TV_FIRST + 5)
        Private Const TVM_GETNEXTITEM As Integer = (TV_FIRST + 10)
        Private Const TVM_SELECTITEM As Integer = (TV_FIRST + 11)
        Private Const TVM_HITTEST As Integer = (TV_FIRST + 17)
        Private Const TVM_ENSUREVISIBLE As Integer = (TV_FIRST + 20)
        Private Const TVM_ENDEDITLABELNOW As Integer = (TV_FIRST + 22)
        Private Const TVM_GETTOOLTIPS As Integer = (TV_FIRST + 25)
        Private Const TVM_GETITEMSTATE As Integer = (TV_FIRST + 39)
        Private Const TVM_MAPACCIDTOHTREEITEM As Integer = (TV_FIRST + 42)
        Private Const TVM_MAPHTREEITEMTOACCID As Integer = (TV_FIRST + 43)
        Private Const TVM_GETITEMW As Integer = (TV_FIRST + 62)
        Private Const TVM_SETITEMW As Integer = (TV_FIRST + 63)
        Private Const TVM_EDITLABELW As Integer = (TV_FIRST + 65)
    
        Private Const TVGN_ROOT As Integer = &H0
        Private Const TVGN_NEXT As Integer = &H1
        Private Const TVGN_PREVIOUS As Integer = &H2
        Private Const TVGN_PARENT As Integer = &H3
        Private Const TVGN_CHILD As Integer = &H4
        Private Const TVGN_CARET As Integer = &H9
    
        Private Const TVE_COLLAPSE As Integer = &H1
        Private Const TVE_EXPAND As Integer = &H2
    
        Private Const TVIF_TEXT As Integer = &H1
        Private Const TVIF_IMAGE As Integer = &H2
        Private Const TVIF_STATE As Integer = &H8
        Private Const TVIF_CHILDREN As Integer = &H40
    
        Private Const TVIS_SELECTED As Integer = &H2
        Private Const TVIS_EXPANDED As Integer = &H20
        Private Const TVIS_STATEIMAGEMASK As Integer = &HF000
    End Class
    
    


    If you say it can`t be done then i`ll try it

    • Marked as answer by HeroCodec Sunday, August 31, 2014 11:13 AM
    Sunday, August 31, 2014 12:59 AM
  • You can look through the msdn documents at the link below to read about what the different messages are used for.

    Tree View Messages


    If you say it can`t be done then i`ll try it

    Sunday, August 31, 2014 1:03 AM
  • Hi,

     Below is an example of how you can select/expand a root node in a Treeview on a 3rd party window by the nodes index. You have to iterate through the nodes to get to the one you want and then use TVM_SELECTITEM and/or TVM_EXPAND. If you want to select a child node you will need to do somewhat the same thing except you would use TVGN_CHILD instead of the TVGN_NEXT. I left all the constants in the code in case you want to do other stuff too.

    Imports System.Runtime.InteropServices
    Imports System.Text
    
    Public Class Form1
        Private TVList As New List(Of IntPtr)
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim hParent As IntPtr = FindWindowW(Nothing, "form1") 'Get the handle of the Parent Window that the TreeView is on
            If hParent <> IntPtr.Zero Then
                Dim hTv As IntPtr = GetTreeviewHandlesFrom(hParent)(0) 'Get the handle of the 1st Treeview on the Parent Window
                If hTv <> IntPtr.Zero Then
                    Dim hRootNode As IntPtr = GetRootNodeHandle(hTv, 2) 'Get the handle of the 3rd root node (2)
                    If hRootNode <> IntPtr.Zero Then
                        SendMessage(hTv, TVM_EXPAND, TVE_EXPAND, hRootNode) 'Expand the node
                        SendMessage(hTv, TVM_SELECTITEM, TVGN_CARET, hRootNode) 'Select the node
                    End If
                End If
            End If
        End Sub
    
        Private Function GetRootNodeHandle(ByVal tvHandle As IntPtr, ByVal NodeIndex As Integer) As IntPtr
            Dim hNode As IntPtr = SendMessage(tvHandle, TVM_GETNEXTITEM, TVGN_ROOT, IntPtr.Zero) 'Get 1st root node handle
            'Iterate to the node wanted if (NodeIndex) is not not the 1st node (0) and get its handle
            For i As Integer = 1 To NodeIndex
                hNode = SendMessage(tvHandle, TVM_GETNEXTITEM, TVGN_NEXT, hNode)
            Next
            Return hNode 'Return the root node handle
        End Function
    
        Private Function GetTreeviewHandlesFrom(ByVal hwnd As IntPtr) As IntPtr()
            TVList.Clear()
            EnumChildWindows(hwnd, AddressOf EnumChildWindowProc, 0)
            Return TVList.ToArray
        End Function
    
        Private Function EnumChildWindowProc(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Integer
            Dim cn As New StringBuilder(255)
            GetClassNameW(hwnd, cn, 255)
            If cn.ToString.ToLower.ToLower.Contains("systreeview32") Then 'Make sure the child window is a Treeview before adding its handle to the List
                TVList.Add(hwnd)
            End If
            Return 1
        End Function
    
        <DllImport("user32.dll", EntryPoint:="FindWindowW")> _
        Private Shared Function FindWindowW(<MarshalAs(UnmanagedType.LPTStr)> ByVal lpClassName As String, <MarshalAs(UnmanagedType.LPTStr)> ByVal lpWindowName As String) As IntPtr
        End Function
    
        <DllImport("user32.dll", EntryPoint:="SendMessageW")> _
        Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As Integer, ByVal lParam As IntPtr) As IntPtr
        End Function
    
        <DllImport("user32.dll", EntryPoint:="GetClassNameW")> _
        Private Shared Function GetClassNameW(ByVal hWnd As IntPtr, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpClassName As System.Text.StringBuilder, ByVal nMaxCount As Integer) As Integer
        End Function
    
        <UnmanagedFunctionPointer(CallingConvention.StdCall)> _
        Private Delegate Function EnumCallBackDelegate(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Integer
    
        <DllImport("user32.dll", EntryPoint:="EnumChildWindows")> _
        Private Shared Function EnumChildWindows(ByVal hWndParent As IntPtr, ByVal lpEnumFunc As EnumCallBackDelegate, ByVal lParam As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <StructLayout(LayoutKind.Sequential)> _
            Private Structure TVITEM
            Public mask As Integer
            Public hItem As IntPtr
            Public State As Integer
            Public stateMask As Integer
            Public pszText As IntPtr
            Public cchTextMax As Integer
            Public iImage As Integer
            Public iSelectedImage As Integer
            Public cChildren As Integer
            Public lParam As IntPtr
        End Structure
    
        Private Const TV_FIRST As Integer = &H1100
        Private Const TVM_EXPAND As Integer = (TV_FIRST + 2)
        Private Const TVM_GETITEMRECT As Integer = (TV_FIRST + 4)
        Private Const TVM_GETCOUNT As Integer = (TV_FIRST + 5)
        Private Const TVM_GETNEXTITEM As Integer = (TV_FIRST + 10)
        Private Const TVM_SELECTITEM As Integer = (TV_FIRST + 11)
        Private Const TVM_HITTEST As Integer = (TV_FIRST + 17)
        Private Const TVM_ENSUREVISIBLE As Integer = (TV_FIRST + 20)
        Private Const TVM_ENDEDITLABELNOW As Integer = (TV_FIRST + 22)
        Private Const TVM_GETTOOLTIPS As Integer = (TV_FIRST + 25)
        Private Const TVM_GETITEMSTATE As Integer = (TV_FIRST + 39)
        Private Const TVM_MAPACCIDTOHTREEITEM As Integer = (TV_FIRST + 42)
        Private Const TVM_MAPHTREEITEMTOACCID As Integer = (TV_FIRST + 43)
        Private Const TVM_GETITEMW As Integer = (TV_FIRST + 62)
        Private Const TVM_SETITEMW As Integer = (TV_FIRST + 63)
        Private Const TVM_EDITLABELW As Integer = (TV_FIRST + 65)
    
        Private Const TVGN_ROOT As Integer = &H0
        Private Const TVGN_NEXT As Integer = &H1
        Private Const TVGN_PREVIOUS As Integer = &H2
        Private Const TVGN_PARENT As Integer = &H3
        Private Const TVGN_CHILD As Integer = &H4
        Private Const TVGN_CARET As Integer = &H9
    
        Private Const TVE_COLLAPSE As Integer = &H1
        Private Const TVE_EXPAND As Integer = &H2
    
        Private Const TVIF_TEXT As Integer = &H1
        Private Const TVIF_IMAGE As Integer = &H2
        Private Const TVIF_STATE As Integer = &H8
        Private Const TVIF_CHILDREN As Integer = &H40
    
        Private Const TVIS_SELECTED As Integer = &H2
        Private Const TVIS_EXPANDED As Integer = &H20
        Private Const TVIS_STATEIMAGEMASK As Integer = &HF000
    End Class
    


    If you say it can`t be done then i`ll try it

    Possible please sent by example in the project because the my face errors

    Sunday, August 31, 2014 2:20 AM
  • Hi,

     You have to set the FindWindow function to find the window that has the TreeView on it. As it is, it finds the first window with the title "Form1" and tries finding the TreeView on it. If the project you are testing this code in has the title of "Form1" then it is finding your current projects window and not finding a TreeView on it.

     
    Dim hParent As IntPtr = FindWindowW(Nothing, "form1") 'Form1 needs to be the title of the window your treeview is on

     

     Notice my application has the title "TreeView Node Select Example" and the application that the TreeView is on has a title of "Form1".


    If you say it can`t be done then i`ll try it

    Sunday, August 31, 2014 2:51 AM
  • Hi,

     You have to set the FindWindow function to find the window that has the TreeView on it. As it is, it finds the first window with the title "Form1" and tries finding the TreeView on it. If the project you are testing this code in has the title of "Form1" then it is finding your current projects window and not finding a TreeView on it.

     
    Dim hParent As IntPtr = FindWindowW(Nothing, "form1") 'Form1 needs to be the title of the window your treeview is on

     

     Notice my application has the title "TreeView Node Select Example" and the application that the TreeView is on has a title of "Form1".


    If you say it can`t be done then i`ll try it

    Thank you too, but I used the handle number Is it possible Modified to use the handle number like this?

    I want to use the Child hWnd instead of FindWindowW

    Sunday, August 31, 2014 3:24 AM
  •  No you cant use a fixed number for a handle. The handle of every window will be different every time the app is closed and re-opened. You will have to use one of the following -> FindWindow, EnumChildWindows or use the Process class to find the process and use its MainWindowHandle. That is the only way you can find the handle.


    If you say it can`t be done then i`ll try it

    • Edited by IronRazerz Sunday, August 31, 2014 3:54 AM
    Sunday, August 31, 2014 3:49 AM
  •  No you cant use a fixed number for a handle. The handle of every window will be different every time the app is closed and re-opened. You will have to use one of the following -> FindWindow, EnumChildWindows or use the Process class to find the process and use its MainWindowHandle. That is the only way you can find the handle.


    If you say it can`t be done then i`ll try it

    My brother, I thank you for your help I have another question,How can I click on the nods 1 next 2 next 3 next 4 next 5 next 6 within the root

    Sunday, August 31, 2014 1:07 PM
  • Hi,

     You can use the TVGN_CHILD message to get the first child node of the root node and then iterate through the child nodes using the TVGN_NEXT message. It is similar to iterating through the root nodes. In this code i added another function called GetChildNodeHandle. You first get the root node handle and then pass that to the GetChildNodeHandle with the index of the child node you want the handle of. Then you can select and/or expand the child node.

     If the child node has children of its own then use the handle that the GetChildNodeHandle returns to call the GetChildNodeHandle function again to get its child nodes.

    Imports System.Runtime.InteropServices
    Imports System.Text
    
    Public Class Form1
        Private TVList As New List(Of IntPtr)
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim hParent As IntPtr = FindWindowW(Nothing, "form1") 'Get the handle of the Parent Window that the TreeView is on
            If hParent <> IntPtr.Zero Then
                Dim hTv As IntPtr = GetTreeviewHandlesFrom(hParent)(0) 'Get the handle of the 1st Treeview on the Parent Window
                If hTv <> IntPtr.Zero Then
                    Dim hRootNode As IntPtr = GetRootNodeHandle(hTv, 2) 'Get the handle of the 3rd root node (2)
                    If hRootNode <> IntPtr.Zero Then
                        SendMessage(hTv, TVM_EXPAND, TVE_EXPAND, hRootNode) 'Expand the root node
                        Dim hChildNode As IntPtr = GetChildNodeHandle(hTv, hRootNode, 1) 'Get the handle of the 2nd child node (1)
                        If hChildNode <> IntPtr.Zero Then
                            SendMessage(hTv, TVM_EXPAND, TVE_EXPAND, hChildNode) 'Expand the child node
                            SendMessage(hTv, TVM_SELECTITEM, TVGN_CARET, hChildNode) 'Select the childnode
                        End If
                    End If
                End If
            End If
        End Sub
    
        Private Function GetRootNodeHandle(ByVal tvHandle As IntPtr, ByVal NodeIndex As Integer) As IntPtr
            Dim hNode As IntPtr = SendMessage(tvHandle, TVM_GETNEXTITEM, TVGN_ROOT, IntPtr.Zero) 'Get 1st root node handle
            'Iterate to the node wanted if (NodeIndex) is not not the 1st node (0) and get its handle
            For i As Integer = 1 To NodeIndex
                hNode = SendMessage(tvHandle, TVM_GETNEXTITEM, TVGN_NEXT, hNode)
            Next
            Return hNode 'Return the root node handle
        End Function
    
        Private Function GetChildNodeHandle(ByVal tvHandle As IntPtr, ByVal hParentNode As IntPtr, ByVal ChildNodeIndex As Integer) As IntPtr
            Dim hChildNode As IntPtr = SendMessage(tvHandle, TVM_GETNEXTITEM, TVGN_CHILD, hParentNode) 'Get the 1st child node
            'Iterate to the child node wanted if (ChildNodeIndex) is not not the 1st node (0) and get its handle
            For i As Integer = 1 To ChildNodeIndex
                hChildNode = SendMessage(tvHandle, TVM_GETNEXTITEM, TVGN_NEXT, hChildNode)
            Next
            Return hChildNode 'Return the child node handle
        End Function
    
        Private Function GetTreeviewHandlesFrom(ByVal hwnd As IntPtr) As IntPtr()
            TVList.Clear()
            EnumChildWindows(hwnd, AddressOf EnumChildWindowProc, 0)
            Return TVList.ToArray
        End Function
    
        Private Function EnumChildWindowProc(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Integer
            Dim cn As New StringBuilder(255)
            GetClassNameW(hwnd, cn, 255)
            If cn.ToString.ToLower.ToLower.Contains("systreeview32") Then 'Make sure the child window is a Treeview before adding its handle to the List
                TVList.Add(hwnd)
            End If
            Return 1
        End Function
    
        <DllImport("user32.dll", EntryPoint:="FindWindowW")> _
        Private Shared Function FindWindowW(<MarshalAs(UnmanagedType.LPTStr)> ByVal lpClassName As String, <MarshalAs(UnmanagedType.LPTStr)> ByVal lpWindowName As String) As IntPtr
        End Function
    
        <DllImport("user32.dll", EntryPoint:="SendMessageW")> _
        Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As Integer, ByVal lParam As IntPtr) As IntPtr
        End Function
    
        <DllImport("user32.dll", EntryPoint:="GetClassNameW")> _
        Private Shared Function GetClassNameW(ByVal hWnd As IntPtr, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpClassName As System.Text.StringBuilder, ByVal nMaxCount As Integer) As Integer
        End Function
    
        <UnmanagedFunctionPointer(CallingConvention.StdCall)> _
        Private Delegate Function EnumCallBackDelegate(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Integer
    
        <DllImport("user32.dll", EntryPoint:="EnumChildWindows")> _
        Private Shared Function EnumChildWindows(ByVal hWndParent As IntPtr, ByVal lpEnumFunc As EnumCallBackDelegate, ByVal lParam As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <StructLayout(LayoutKind.Sequential)> _
            Private Structure TVITEM
            Public mask As Integer
            Public hItem As IntPtr
            Public State As Integer
            Public stateMask As Integer
            Public pszText As IntPtr
            Public cchTextMax As Integer
            Public iImage As Integer
            Public iSelectedImage As Integer
            Public cChildren As Integer
            Public lParam As IntPtr
        End Structure
    
        Private Const TV_FIRST As Integer = &H1100
        Private Const TVM_EXPAND As Integer = (TV_FIRST + 2)
        Private Const TVM_GETITEMRECT As Integer = (TV_FIRST + 4)
        Private Const TVM_GETCOUNT As Integer = (TV_FIRST + 5)
        Private Const TVM_GETNEXTITEM As Integer = (TV_FIRST + 10)
        Private Const TVM_SELECTITEM As Integer = (TV_FIRST + 11)
        Private Const TVM_HITTEST As Integer = (TV_FIRST + 17)
        Private Const TVM_ENSUREVISIBLE As Integer = (TV_FIRST + 20)
        Private Const TVM_ENDEDITLABELNOW As Integer = (TV_FIRST + 22)
        Private Const TVM_GETTOOLTIPS As Integer = (TV_FIRST + 25)
        Private Const TVM_GETITEMSTATE As Integer = (TV_FIRST + 39)
        Private Const TVM_MAPACCIDTOHTREEITEM As Integer = (TV_FIRST + 42)
        Private Const TVM_MAPHTREEITEMTOACCID As Integer = (TV_FIRST + 43)
        Private Const TVM_GETITEMW As Integer = (TV_FIRST + 62)
        Private Const TVM_SETITEMW As Integer = (TV_FIRST + 63)
        Private Const TVM_EDITLABELW As Integer = (TV_FIRST + 65)
    
        Private Const TVGN_ROOT As Integer = &H0
        Private Const TVGN_NEXT As Integer = &H1
        Private Const TVGN_PREVIOUS As Integer = &H2
        Private Const TVGN_PARENT As Integer = &H3
        Private Const TVGN_CHILD As Integer = &H4
        Private Const TVGN_CARET As Integer = &H9
    
        Private Const TVE_COLLAPSE As Integer = &H1
        Private Const TVE_EXPAND As Integer = &H2
    
        Private Const TVIF_TEXT As Integer = &H1
        Private Const TVIF_IMAGE As Integer = &H2
        Private Const TVIF_STATE As Integer = &H8
        Private Const TVIF_CHILDREN As Integer = &H40
    
        Private Const TVIS_SELECTED As Integer = &H2
        Private Const TVIS_EXPANDED As Integer = &H20
        Private Const TVIS_STATEIMAGEMASK As Integer = &HF000
    End Class
    
    


    If you say it can`t be done then i`ll try it

    Sunday, August 31, 2014 2:58 PM
  • Hi,

     You can use the TVGN_CHILD message to get the first child node of the root node and then iterate through the child nodes using the TVGN_NEXT message. It is similar to iterating through the root nodes. In this code i added another function called GetChildNodeHandle. You first get the root node handle and then pass that to the GetChildNodeHandle with the index of the child node you want the handle of. Then you can select and/or expand the child node.

     If the child node has children of its own then use the handle that the GetChildNodeHandle returns to call the GetChildNodeHandle function again to get its child nodes.

    Imports System.Runtime.InteropServices
    Imports System.Text
    
    Public Class Form1
        Private TVList As New List(Of IntPtr)
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim hParent As IntPtr = FindWindowW(Nothing, "form1") 'Get the handle of the Parent Window that the TreeView is on
            If hParent <> IntPtr.Zero Then
                Dim hTv As IntPtr = GetTreeviewHandlesFrom(hParent)(0) 'Get the handle of the 1st Treeview on the Parent Window
                If hTv <> IntPtr.Zero Then
                    Dim hRootNode As IntPtr = GetRootNodeHandle(hTv, 2) 'Get the handle of the 3rd root node (2)
                    If hRootNode <> IntPtr.Zero Then
                        SendMessage(hTv, TVM_EXPAND, TVE_EXPAND, hRootNode) 'Expand the root node
                        Dim hChildNode As IntPtr = GetChildNodeHandle(hTv, hRootNode, 1) 'Get the handle of the 2nd child node (1)
                        If hChildNode <> IntPtr.Zero Then
                            SendMessage(hTv, TVM_EXPAND, TVE_EXPAND, hChildNode) 'Expand the child node
                            SendMessage(hTv, TVM_SELECTITEM, TVGN_CARET, hChildNode) 'Select the childnode
                        End If
                    End If
                End If
            End If
        End Sub
    
        Private Function GetRootNodeHandle(ByVal tvHandle As IntPtr, ByVal NodeIndex As Integer) As IntPtr
            Dim hNode As IntPtr = SendMessage(tvHandle, TVM_GETNEXTITEM, TVGN_ROOT, IntPtr.Zero) 'Get 1st root node handle
            'Iterate to the node wanted if (NodeIndex) is not not the 1st node (0) and get its handle
            For i As Integer = 1 To NodeIndex
                hNode = SendMessage(tvHandle, TVM_GETNEXTITEM, TVGN_NEXT, hNode)
            Next
            Return hNode 'Return the root node handle
        End Function
    
        Private Function GetChildNodeHandle(ByVal tvHandle As IntPtr, ByVal hParentNode As IntPtr, ByVal ChildNodeIndex As Integer) As IntPtr
            Dim hChildNode As IntPtr = SendMessage(tvHandle, TVM_GETNEXTITEM, TVGN_CHILD, hParentNode) 'Get the 1st child node
            'Iterate to the child node wanted if (ChildNodeIndex) is not not the 1st node (0) and get its handle
            For i As Integer = 1 To ChildNodeIndex
                hChildNode = SendMessage(tvHandle, TVM_GETNEXTITEM, TVGN_NEXT, hChildNode)
            Next
            Return hChildNode 'Return the child node handle
        End Function
    
        Private Function GetTreeviewHandlesFrom(ByVal hwnd As IntPtr) As IntPtr()
            TVList.Clear()
            EnumChildWindows(hwnd, AddressOf EnumChildWindowProc, 0)
            Return TVList.ToArray
        End Function
    
        Private Function EnumChildWindowProc(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Integer
            Dim cn As New StringBuilder(255)
            GetClassNameW(hwnd, cn, 255)
            If cn.ToString.ToLower.ToLower.Contains("systreeview32") Then 'Make sure the child window is a Treeview before adding its handle to the List
                TVList.Add(hwnd)
            End If
            Return 1
        End Function
    
        <DllImport("user32.dll", EntryPoint:="FindWindowW")> _
        Private Shared Function FindWindowW(<MarshalAs(UnmanagedType.LPTStr)> ByVal lpClassName As String, <MarshalAs(UnmanagedType.LPTStr)> ByVal lpWindowName As String) As IntPtr
        End Function
    
        <DllImport("user32.dll", EntryPoint:="SendMessageW")> _
        Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As Integer, ByVal lParam As IntPtr) As IntPtr
        End Function
    
        <DllImport("user32.dll", EntryPoint:="GetClassNameW")> _
        Private Shared Function GetClassNameW(ByVal hWnd As IntPtr, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpClassName As System.Text.StringBuilder, ByVal nMaxCount As Integer) As Integer
        End Function
    
        <UnmanagedFunctionPointer(CallingConvention.StdCall)> _
        Private Delegate Function EnumCallBackDelegate(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Integer
    
        <DllImport("user32.dll", EntryPoint:="EnumChildWindows")> _
        Private Shared Function EnumChildWindows(ByVal hWndParent As IntPtr, ByVal lpEnumFunc As EnumCallBackDelegate, ByVal lParam As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <StructLayout(LayoutKind.Sequential)> _
            Private Structure TVITEM
            Public mask As Integer
            Public hItem As IntPtr
            Public State As Integer
            Public stateMask As Integer
            Public pszText As IntPtr
            Public cchTextMax As Integer
            Public iImage As Integer
            Public iSelectedImage As Integer
            Public cChildren As Integer
            Public lParam As IntPtr
        End Structure
    
        Private Const TV_FIRST As Integer = &H1100
        Private Const TVM_EXPAND As Integer = (TV_FIRST + 2)
        Private Const TVM_GETITEMRECT As Integer = (TV_FIRST + 4)
        Private Const TVM_GETCOUNT As Integer = (TV_FIRST + 5)
        Private Const TVM_GETNEXTITEM As Integer = (TV_FIRST + 10)
        Private Const TVM_SELECTITEM As Integer = (TV_FIRST + 11)
        Private Const TVM_HITTEST As Integer = (TV_FIRST + 17)
        Private Const TVM_ENSUREVISIBLE As Integer = (TV_FIRST + 20)
        Private Const TVM_ENDEDITLABELNOW As Integer = (TV_FIRST + 22)
        Private Const TVM_GETTOOLTIPS As Integer = (TV_FIRST + 25)
        Private Const TVM_GETITEMSTATE As Integer = (TV_FIRST + 39)
        Private Const TVM_MAPACCIDTOHTREEITEM As Integer = (TV_FIRST + 42)
        Private Const TVM_MAPHTREEITEMTOACCID As Integer = (TV_FIRST + 43)
        Private Const TVM_GETITEMW As Integer = (TV_FIRST + 62)
        Private Const TVM_SETITEMW As Integer = (TV_FIRST + 63)
        Private Const TVM_EDITLABELW As Integer = (TV_FIRST + 65)
    
        Private Const TVGN_ROOT As Integer = &H0
        Private Const TVGN_NEXT As Integer = &H1
        Private Const TVGN_PREVIOUS As Integer = &H2
        Private Const TVGN_PARENT As Integer = &H3
        Private Const TVGN_CHILD As Integer = &H4
        Private Const TVGN_CARET As Integer = &H9
    
        Private Const TVE_COLLAPSE As Integer = &H1
        Private Const TVE_EXPAND As Integer = &H2
    
        Private Const TVIF_TEXT As Integer = &H1
        Private Const TVIF_IMAGE As Integer = &H2
        Private Const TVIF_STATE As Integer = &H8
        Private Const TVIF_CHILDREN As Integer = &H40
    
        Private Const TVIS_SELECTED As Integer = &H2
        Private Const TVIS_EXPANDED As Integer = &H20
        Private Const TVIS_STATEIMAGEMASK As Integer = &HF000
    End Class
    


    If you say it can`t be done then i`ll try it

    You are a professor of professional and I am thanking you very how can use 

    SendMessage(hTv, BM_CLICK, IntPtr.Zero, hChildNode)

    in code

    Sunday, August 31, 2014 4:20 PM
  • You are a professor of professional and I am thanking you very how can use 

    SendMessage(hTv, BM_CLICK, IntPtr.Zero, hChildNode)

    in code

     Hi,

     The BM_Click message is a message used for buttons only. You can not use this message for a Treeview Node. The only way you can make the mouse click a node in a treeview is to get the rectangle area of the screen that the node is located in and then use something like the SendInput or mouse_event API functions to actually move the mouse to the rectangle area of the screen and simulate a mouse click.

      I can try to create an example of doing this but, i want to make sure you understand that it will actually move the cursor to that area of the screen to simulate a mouse click before i take the time to create an example of that. It will require a bit more code to do this too. Let me know if you have read this and understand it before i try making an example code.

     


    If you say it can`t be done then i`ll try it

    Sunday, August 31, 2014 5:05 PM
  • You are a professor of professional and I am thanking you very how can use 

    SendMessage(hTv, BM_CLICK, IntPtr.Zero, hChildNode)

    in code

     Hi,

     The BM_Click message is a message used for buttons only. You can not use this message for a Treeview Node. The only way you can make the mouse click a node in a treeview is to get the rectangle area of the screen that the node is located in and then use something like the SendInput or mouse_event API functions to actually move the mouse to the rectangle area of the screen and simulate a mouse click.

      I can try to create an example of doing this but, i want to make sure you understand that it will actually move the cursor to that area of the screen to simulate a mouse click before i take the time to create an example of that. It will require a bit more code to do this too. Let me know if you have read this and understand it before i try making an example code.

     


    If you say it can`t be done then i`ll try it

    Thank you very much for your cooperation with me, I want clicks with Each item in the waiting example How do I use NM_CLICK node

    • Edited by HeroCodec Sunday, August 31, 2014 5:47 PM
    Sunday, August 31, 2014 5:35 PM
  • Thank you very much for your cooperation with me, I want clicks with Each item in the waiting example How do I use NM_CLICK node

     The NM_CLICK is a message that the treeview control itself sends to its parent window in a WM_NOTIFY message to indicate that the left mouse button was clicked within the treeview control`s client area. It can not be sent to a treeview control or its parent window from another application.

     If you read the WM_NOTIFY message documents on msdn you will see it says.

    "For Windows 2000 and later systems, the WM_NOTIFY message cannot be sent between processes."


    If you say it can`t be done then i`ll try it

    • Edited by IronRazerz Sunday, August 31, 2014 7:04 PM
    Sunday, August 31, 2014 7:02 PM
  • thanks to share it
    Sunday, August 31, 2014 7:04 PM
  • Thank you very much for your cooperation with me, I want clicks with Each item in the waiting example How do I use NM_CLICK node

     The NM_CLICK is a message that the treeview control itself sends to its parent window in a WM_NOTIFY message to indicate that the left mouse button was clicked within the treeview control`s client area. It can not be sent to a treeview control or its parent window from another application.

     If you read the WM_NOTIFY message documents on msdn you will see it says.

    "For Windows 2000 and later systems, the WM_NOTIFY message cannot be sent between processes."


    If you say it can`t be done then i`ll try it

    I want any way you click on the node Is there a way?
    Sunday, August 31, 2014 7:37 PM
  • Well, as i said, you will need to get the rectangle area of the node and then move the mouse to that rectangle area of the screen and then simulate a mouse click. The treeview node will need to be visible on the screen in order for it to be clicked other wise this method will not work.

     In the code below i have added another Sub and a bunch more API functions, constants, and the RECT structure. The Sub is called ClickNodeWithMouse. You will need to find the node handle as has been done in the prior examples and then you can call the ClickNodeWithMouse sub to click the mouse on it. I did not know if you wanted to make a single or double left click or maybe a right click so i made the sub with a few parameters that you can set to make it do whatever you need.

     The example below finds the handle to the 2nd child node of the 3rd root node and then double clicks the left mouse button on it. Then it returns the cursor to the position it was at when the sub was called. In this case it returns it back over the button on my form that i click to make all this happen. It should be quick enough that you will not really notice the cursor moving. You can also set the ReturnMousePosition parameter of the Sub to false so that the mouse is left over the node if you want to do that.

    Imports System.Runtime.InteropServices
    Imports System.Text
    
    Public Class Form1
        Private TVList As New List(Of IntPtr)
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim hParent As IntPtr = FindWindowW(Nothing, "form1") 'Get the handle of the Parent Window that the TreeView is on
            If hParent <> IntPtr.Zero Then
                Dim hTv As IntPtr = GetTreeviewHandlesFrom(hParent)(0) 'Get the handle of the 1st Treeview on the Parent Window
                If hTv <> IntPtr.Zero Then
                    Dim hRootNode As IntPtr = GetRootNodeHandle(hTv, 2) 'Get the handle of the 3rd root node (2)
                    If hRootNode <> IntPtr.Zero Then
                        SendMessageW(hTv, TVM_EXPAND, TVE_EXPAND, hRootNode) 'Expand the root node
                        Dim hChildNode As IntPtr = GetChildNodeHandle(hTv, hRootNode, 1) 'Get the handle of the 2nd child node (1)
                        If hChildNode <> IntPtr.Zero Then
                            'SendMessageW(hTv, TVM_EXPAND, TVE_EXPAND, hChildNode) 'Expand the child node
                            'SendMessageW(hTv, TVM_SELECTITEM, TVGN_CARET, hChildNode) 'Select the childnode
    
                            'moves the cursor to the node, double clicks the left mouse button, and then returns the cursor to its original position
                            ClickNodeWithMouse(hTv, hChildNode, False, True, True)
                        End If
                    End If
                End If
            End If
        End Sub
    
        Private Function GetRootNodeHandle(ByVal tvHandle As IntPtr, ByVal NodeIndex As Integer) As IntPtr
            Dim hNode As IntPtr = SendMessageW(tvHandle, TVM_GETNEXTITEM, TVGN_ROOT, IntPtr.Zero) 'Get 1st root node handle
            'Iterate to the node wanted if (NodeIndex) is not not the 1st node (0) and get its handle
            For i As Integer = 1 To NodeIndex
                hNode = SendMessageW(tvHandle, TVM_GETNEXTITEM, TVGN_NEXT, hNode)
            Next
            Return hNode 'Return the root node handle
        End Function
    
        Private Function GetChildNodeHandle(ByVal tvHandle As IntPtr, ByVal hParentNode As IntPtr, ByVal ChildNodeIndex As Integer) As IntPtr
            Dim hChildNode As IntPtr = SendMessageW(tvHandle, TVM_GETNEXTITEM, TVGN_CHILD, hParentNode) 'Get the 1st child node
            'Iterate to the child node wanted if (ChildNodeIndex) is not not the 1st node (0) and get its handle
            For i As Integer = 1 To ChildNodeIndex
                hChildNode = SendMessageW(tvHandle, TVM_GETNEXTITEM, TVGN_NEXT, hChildNode)
            Next
            Return hChildNode 'Return the child node handle
        End Function
    
        ''' <summary>Moves the cursor to the node and clicks the mouse button.</summary>
        ''' <param name="tvHandle">Handle to the treeview control</param>
        ''' <param name="hNode">Handle to the treeview node to click</param>
        ''' <param name="RightClick">True to Right click the mouse. False to Left click the mouse.</param>
        ''' <param name="DoubleClick">True to double click the mouse button (only for left click).</param>
        ''' <param name="ReturnMousePosition">True to return the mouse cursor to its original position after clicking</param>
        Private Sub ClickNodeWithMouse(ByVal tvHandle As IntPtr, ByVal hNode As IntPtr, ByVal RightClick As Boolean, ByVal DoubleClick As Boolean, ByVal ReturnMousePosition As Boolean)
            Dim procId As Integer = Nothing
            GetWindowThreadProcessId(tvHandle, procId)
            Dim hProc As IntPtr = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, False, procId)
    
            Dim nRect As New RECT
            nRect.left = hNode.ToInt32
    
            Dim tvNodeRectPtr As IntPtr = VirtualAllocEx(hProc, IntPtr.Zero, Marshal.SizeOf(nRect), MEM_COMMIT, PAGE_READWRITE)
            WriteProcessMemory(hProc, tvNodeRectPtr, nRect, Marshal.SizeOf(nRect), 0)
    
            SendMessageW(tvHandle, TVM_GETITEMRECT, 1, tvNodeRectPtr)
    
            ReadProcessMemory(hProc, tvNodeRectPtr, nRect, Marshal.SizeOf(nRect), 0)
    
            VirtualFreeEx(hProc, tvNodeRectPtr, 0, MEM_RELEASE)
            CloseHandle(hProc)
    
            Dim tvRect As New RECT
            GetWindowRect(tvHandle, tvRect)
    
            Dim CurrentCursorPosition As Point = Cursor.Position
    
            Cursor.Position = New Point(tvRect.left + nRect.left + 20, tvRect.top + nRect.top + CInt((nRect.bottom - nRect.top) / 2))
            If RightClick Then
                mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0)
                mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0)
            Else
                mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
                mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)
                If DoubleClick Then
                    mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
                    mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)
                End If
            End If
    
            If ReturnMousePosition Then
                Cursor.Position = CurrentCursorPosition
            End If
        End Sub
    
        Private Function GetTreeviewHandlesFrom(ByVal hwnd As IntPtr) As IntPtr()
            TVList.Clear()
            EnumChildWindows(hwnd, AddressOf EnumChildWindowProc, 0)
            Return TVList.ToArray
        End Function
    
        Private Function EnumChildWindowProc(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Integer
            Dim cn As New StringBuilder(255)
            GetClassNameW(hwnd, cn, 255)
            If cn.ToString.ToLower.ToLower.Contains("systreeview32") Then 'Make sure the child window is a Treeview before adding its handle to the List
                TVList.Add(hwnd)
            End If
            Return 1
        End Function
    
        <DllImport("user32.dll", EntryPoint:="FindWindowW")> _
        Private Shared Function FindWindowW(<MarshalAs(UnmanagedType.LPTStr)> ByVal lpClassName As String, <MarshalAs(UnmanagedType.LPTStr)> ByVal lpWindowName As String) As IntPtr
        End Function
    
        <DllImport("user32.dll", EntryPoint:="SendMessageW")> _
        Private Shared Function SendMessageW(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As Integer, ByVal lParam As IntPtr) As IntPtr
        End Function
    
        <DllImport("user32.dll", EntryPoint:="GetClassNameW")> _
        Private Shared Function GetClassNameW(ByVal hWnd As IntPtr, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpClassName As System.Text.StringBuilder, ByVal nMaxCount As Integer) As Integer
        End Function
    
        <UnmanagedFunctionPointer(CallingConvention.StdCall)> _
        Private Delegate Function EnumCallBackDelegate(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Integer
    
        <DllImport("user32.dll", EntryPoint:="EnumChildWindows")> _
        Private Shared Function EnumChildWindows(ByVal hWndParent As IntPtr, ByVal lpEnumFunc As EnumCallBackDelegate, ByVal lParam As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("kernel32.dll", EntryPoint:="WriteProcessMemory")> _
        Private Shared Function WriteProcessMemory(ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByRef lpBuffer As RECT, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("kernel32.dll", EntryPoint:="ReadProcessMemory")> _
        Private Shared Function ReadProcessMemory(ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByRef lpBuffer As RECT, ByVal nSize As Integer, ByRef lpNumberOfBytesRead As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("kernel32.dll", EntryPoint:="OpenProcess")> _
        Private Shared Function OpenProcess(ByVal dwDesiredAccess As UInteger, <MarshalAs(UnmanagedType.Bool)> ByVal bInheritHandle As Boolean, ByVal dwProcessId As Integer) As IntPtr
        End Function
    
        <DllImport("kernel32.dll", EntryPoint:="CloseHandle")> _
        Private Shared Function CloseHandle(ByVal hObject As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("kernel32.dll", EntryPoint:="VirtualAllocEx")> _
        Private Shared Function VirtualAllocEx(ByVal hProcess As IntPtr, ByVal lpAddress As IntPtr, ByVal dwSize As Integer, ByVal flAllocationType As UInteger, ByVal flProtect As UInteger) As IntPtr
        End Function
    
        <DllImportAttribute("kernel32.dll", EntryPoint:="VirtualFreeEx")> _
        Private Shared Function VirtualFreeEx(ByVal hProcess As IntPtr, ByVal lpAddress As IntPtr, ByVal dwSize As UInteger, ByVal dwFreeType As UInteger) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("user32.dll", EntryPoint:="GetWindowThreadProcessId")> _
        Private Shared Function GetWindowThreadProcessId(ByVal hWnd As IntPtr, ByRef lpdwProcessId As Integer) As Integer
        End Function
    
        <DllImport("user32.dll", EntryPoint:="GetWindowRect")> _
        Private Shared Function GetWindowRect(ByVal hWnd As IntPtr, ByRef lpRect As RECT) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("user32.dll", EntryPoint:="mouse_event")> _
        Private Shared Sub mouse_event(ByVal dwFlags As UInteger, ByVal dx As Integer, ByVal dy As Integer, ByVal dwData As Integer, ByVal dwExtraInfo As UInteger)
        End Sub
    
        <StructLayout(LayoutKind.Sequential)> _
        Private Structure RECT
            Public left As Integer
            Public top As Integer
            Public right As Integer
            Public bottom As Integer
        End Structure
    
        <StructLayout(LayoutKind.Sequential)> _
            Private Structure TVITEM
            Public mask As Integer
            Public hItem As IntPtr
            Public State As Integer
            Public stateMask As Integer
            Public pszText As IntPtr
            Public cchTextMax As Integer
            Public iImage As Integer
            Public iSelectedImage As Integer
            Public cChildren As Integer
            Public lParam As IntPtr
        End Structure
    
        Private Const TV_FIRST As Integer = &H1100
        Private Const TVM_EXPAND As Integer = (TV_FIRST + 2)
        Private Const TVM_GETITEMRECT As Integer = (TV_FIRST + 4)
        Private Const TVM_GETCOUNT As Integer = (TV_FIRST + 5)
        Private Const TVM_GETNEXTITEM As Integer = (TV_FIRST + 10)
        Private Const TVM_SELECTITEM As Integer = (TV_FIRST + 11)
        Private Const TVM_HITTEST As Integer = (TV_FIRST + 17)
        Private Const TVM_ENSUREVISIBLE As Integer = (TV_FIRST + 20)
        Private Const TVM_ENDEDITLABELNOW As Integer = (TV_FIRST + 22)
        Private Const TVM_GETTOOLTIPS As Integer = (TV_FIRST + 25)
        Private Const TVM_GETITEMSTATE As Integer = (TV_FIRST + 39)
        Private Const TVM_MAPACCIDTOHTREEITEM As Integer = (TV_FIRST + 42)
        Private Const TVM_MAPHTREEITEMTOACCID As Integer = (TV_FIRST + 43)
        Private Const TVM_GETITEMW As Integer = (TV_FIRST + 62)
        Private Const TVM_SETITEMW As Integer = (TV_FIRST + 63)
        Private Const TVM_EDITLABELW As Integer = (TV_FIRST + 65)
    
        Private Const TVGN_ROOT As Integer = &H0
        Private Const TVGN_NEXT As Integer = &H1
        Private Const TVGN_PREVIOUS As Integer = &H2
        Private Const TVGN_PARENT As Integer = &H3
        Private Const TVGN_CHILD As Integer = &H4
        Private Const TVGN_CARET As Integer = &H9
    
        Private Const TVE_COLLAPSE As Integer = &H1
        Private Const TVE_EXPAND As Integer = &H2
    
        Private Const TVIF_TEXT As Integer = &H1
        Private Const TVIF_IMAGE As Integer = &H2
        Private Const TVIF_STATE As Integer = &H8
        Private Const TVIF_CHILDREN As Integer = &H40
    
        Private Const TVIS_SELECTED As Integer = &H2
        Private Const TVIS_EXPANDED As Integer = &H20
        Private Const TVIS_STATEIMAGEMASK As Integer = &HF000
    
        Private Const MEM_COMMIT As UInteger = &H1000
        Private Const MEM_RELEASE As UInteger = &H8000
        Private Const PAGE_READWRITE As UInteger = &H4
    
        Private Const PROCESS_VM_READ As UInteger = &H10
        Private Const PROCESS_VM_WRITE As UInteger = &H20
        Private Const PROCESS_VM_OPERATION As UInteger = &H8
    
        Private Const MOUSEEVENTF_LEFTDOWN As Integer = &H2
        Private Const MOUSEEVENTF_LEFTUP As Integer = &H4
        Private Const MOUSEEVENTF_RIGHTDOWN As Integer = &H8
        Private Const MOUSEEVENTF_RIGHTUP As Integer = &H10
    
    End Class
    
    

     Here is the above example showing that it expands the nodes so that the 2nd child node of the 3rd root node is visible and then double clicks the left mouse button on it which expands the child node. Then it returns the mouse back to the button on my form. Then when i click the button a second time it does the same thing except it closes the child node when it is double clicked this time.

     

     This does seem like a lot of work just to click on a node in a 3rd party window. Perhaps it would be easier to just manually click it instead of going through all of this.  8)


    If you say it can`t be done then i`ll try it

    • Marked as answer by HeroCodec Sunday, August 31, 2014 11:00 PM
    Sunday, August 31, 2014 9:50 PM
  • Well, as i said, you will need to get the rectangle area of the node and then move the mouse to that rectangle area of the screen and then simulate a mouse click. The treeview node will need to be visible on the screen in order for it to be clicked other wise this method will not work.

     In the code below i have added another Sub and a bunch more API functions, constants, and the RECT structure. The Sub is called ClickNodeWithMouse. You will need to find the node handle as has been done in the prior examples and then you can call the ClickNodeWithMouse sub to click the mouse on it. I did not know if you wanted to make a single or double left click or maybe a right click so i made the sub with a few parameters that you can set to make it do whatever you need.

     The example below finds the handle to the 2nd child node of the 3rd root node and then double clicks the left mouse button on it. Then it returns the cursor to the position it was at when the sub was called. In this case it returns it back over the button on my form that i click to make all this happen. It should be quick enough that you will not really notice the cursor moving. You can also set the ReturnMousePosition parameter of the Sub to false so that the mouse is left over the node if you want to do that.

    Imports System.Runtime.InteropServices
    Imports System.Text
    
    Public Class Form1
        Private TVList As New List(Of IntPtr)
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim hParent As IntPtr = FindWindowW(Nothing, "form1") 'Get the handle of the Parent Window that the TreeView is on
            If hParent <> IntPtr.Zero Then
                Dim hTv As IntPtr = GetTreeviewHandlesFrom(hParent)(0) 'Get the handle of the 1st Treeview on the Parent Window
                If hTv <> IntPtr.Zero Then
                    Dim hRootNode As IntPtr = GetRootNodeHandle(hTv, 2) 'Get the handle of the 3rd root node (2)
                    If hRootNode <> IntPtr.Zero Then
                        SendMessageW(hTv, TVM_EXPAND, TVE_EXPAND, hRootNode) 'Expand the root node
                        Dim hChildNode As IntPtr = GetChildNodeHandle(hTv, hRootNode, 1) 'Get the handle of the 2nd child node (1)
                        If hChildNode <> IntPtr.Zero Then
                            'SendMessageW(hTv, TVM_EXPAND, TVE_EXPAND, hChildNode) 'Expand the child node
                            'SendMessageW(hTv, TVM_SELECTITEM, TVGN_CARET, hChildNode) 'Select the childnode
    
                            'moves the cursor to the node, double clicks the left mouse button, and then returns the cursor to its original position
                            ClickNodeWithMouse(hTv, hChildNode, False, True, True)
                        End If
                    End If
                End If
            End If
        End Sub
    
        Private Function GetRootNodeHandle(ByVal tvHandle As IntPtr, ByVal NodeIndex As Integer) As IntPtr
            Dim hNode As IntPtr = SendMessageW(tvHandle, TVM_GETNEXTITEM, TVGN_ROOT, IntPtr.Zero) 'Get 1st root node handle
            'Iterate to the node wanted if (NodeIndex) is not not the 1st node (0) and get its handle
            For i As Integer = 1 To NodeIndex
                hNode = SendMessageW(tvHandle, TVM_GETNEXTITEM, TVGN_NEXT, hNode)
            Next
            Return hNode 'Return the root node handle
        End Function
    
        Private Function GetChildNodeHandle(ByVal tvHandle As IntPtr, ByVal hParentNode As IntPtr, ByVal ChildNodeIndex As Integer) As IntPtr
            Dim hChildNode As IntPtr = SendMessageW(tvHandle, TVM_GETNEXTITEM, TVGN_CHILD, hParentNode) 'Get the 1st child node
            'Iterate to the child node wanted if (ChildNodeIndex) is not not the 1st node (0) and get its handle
            For i As Integer = 1 To ChildNodeIndex
                hChildNode = SendMessageW(tvHandle, TVM_GETNEXTITEM, TVGN_NEXT, hChildNode)
            Next
            Return hChildNode 'Return the child node handle
        End Function
    
        ''' <summary>Moves the cursor to the node and clicks the mouse button.</summary>
        ''' <param name="tvHandle">Handle to the treeview control</param>
        ''' <param name="hNode">Handle to the treeview node to click</param>
        ''' <param name="RightClick">True to Right click the mouse. False to Left click the mouse.</param>
        ''' <param name="DoubleClick">True to double click the mouse button (only for left click).</param>
        ''' <param name="ReturnMousePosition">True to return the mouse cursor to its original position after clicking</param>
        Private Sub ClickNodeWithMouse(ByVal tvHandle As IntPtr, ByVal hNode As IntPtr, ByVal RightClick As Boolean, ByVal DoubleClick As Boolean, ByVal ReturnMousePosition As Boolean)
            Dim procId As Integer = Nothing
            GetWindowThreadProcessId(tvHandle, procId)
            Dim hProc As IntPtr = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, False, procId)
    
            Dim nRect As New RECT
            nRect.left = hNode.ToInt32
    
            Dim tvNodeRectPtr As IntPtr = VirtualAllocEx(hProc, IntPtr.Zero, Marshal.SizeOf(nRect), MEM_COMMIT, PAGE_READWRITE)
            WriteProcessMemory(hProc, tvNodeRectPtr, nRect, Marshal.SizeOf(nRect), 0)
    
            SendMessageW(tvHandle, TVM_GETITEMRECT, 1, tvNodeRectPtr)
    
            ReadProcessMemory(hProc, tvNodeRectPtr, nRect, Marshal.SizeOf(nRect), 0)
    
            VirtualFreeEx(hProc, tvNodeRectPtr, 0, MEM_RELEASE)
            CloseHandle(hProc)
    
            Dim tvRect As New RECT
            GetWindowRect(tvHandle, tvRect)
    
            Dim CurrentCursorPosition As Point = Cursor.Position
    
            Cursor.Position = New Point(tvRect.left + nRect.left + 20, tvRect.top + nRect.top + CInt((nRect.bottom - nRect.top) / 2))
            If RightClick Then
                mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0)
                mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0)
            Else
                mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
                mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)
                If DoubleClick Then
                    mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
                    mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)
                End If
            End If
    
            If ReturnMousePosition Then
                Cursor.Position = CurrentCursorPosition
            End If
        End Sub
    
        Private Function GetTreeviewHandlesFrom(ByVal hwnd As IntPtr) As IntPtr()
            TVList.Clear()
            EnumChildWindows(hwnd, AddressOf EnumChildWindowProc, 0)
            Return TVList.ToArray
        End Function
    
        Private Function EnumChildWindowProc(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Integer
            Dim cn As New StringBuilder(255)
            GetClassNameW(hwnd, cn, 255)
            If cn.ToString.ToLower.ToLower.Contains("systreeview32") Then 'Make sure the child window is a Treeview before adding its handle to the List
                TVList.Add(hwnd)
            End If
            Return 1
        End Function
    
        <DllImport("user32.dll", EntryPoint:="FindWindowW")> _
        Private Shared Function FindWindowW(<MarshalAs(UnmanagedType.LPTStr)> ByVal lpClassName As String, <MarshalAs(UnmanagedType.LPTStr)> ByVal lpWindowName As String) As IntPtr
        End Function
    
        <DllImport("user32.dll", EntryPoint:="SendMessageW")> _
        Private Shared Function SendMessageW(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As Integer, ByVal lParam As IntPtr) As IntPtr
        End Function
    
        <DllImport("user32.dll", EntryPoint:="GetClassNameW")> _
        Private Shared Function GetClassNameW(ByVal hWnd As IntPtr, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpClassName As System.Text.StringBuilder, ByVal nMaxCount As Integer) As Integer
        End Function
    
        <UnmanagedFunctionPointer(CallingConvention.StdCall)> _
        Private Delegate Function EnumCallBackDelegate(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Integer
    
        <DllImport("user32.dll", EntryPoint:="EnumChildWindows")> _
        Private Shared Function EnumChildWindows(ByVal hWndParent As IntPtr, ByVal lpEnumFunc As EnumCallBackDelegate, ByVal lParam As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("kernel32.dll", EntryPoint:="WriteProcessMemory")> _
        Private Shared Function WriteProcessMemory(ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByRef lpBuffer As RECT, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("kernel32.dll", EntryPoint:="ReadProcessMemory")> _
        Private Shared Function ReadProcessMemory(ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByRef lpBuffer As RECT, ByVal nSize As Integer, ByRef lpNumberOfBytesRead As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("kernel32.dll", EntryPoint:="OpenProcess")> _
        Private Shared Function OpenProcess(ByVal dwDesiredAccess As UInteger, <MarshalAs(UnmanagedType.Bool)> ByVal bInheritHandle As Boolean, ByVal dwProcessId As Integer) As IntPtr
        End Function
    
        <DllImport("kernel32.dll", EntryPoint:="CloseHandle")> _
        Private Shared Function CloseHandle(ByVal hObject As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("kernel32.dll", EntryPoint:="VirtualAllocEx")> _
        Private Shared Function VirtualAllocEx(ByVal hProcess As IntPtr, ByVal lpAddress As IntPtr, ByVal dwSize As Integer, ByVal flAllocationType As UInteger, ByVal flProtect As UInteger) As IntPtr
        End Function
    
        <DllImportAttribute("kernel32.dll", EntryPoint:="VirtualFreeEx")> _
        Private Shared Function VirtualFreeEx(ByVal hProcess As IntPtr, ByVal lpAddress As IntPtr, ByVal dwSize As UInteger, ByVal dwFreeType As UInteger) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("user32.dll", EntryPoint:="GetWindowThreadProcessId")> _
        Private Shared Function GetWindowThreadProcessId(ByVal hWnd As IntPtr, ByRef lpdwProcessId As Integer) As Integer
        End Function
    
        <DllImport("user32.dll", EntryPoint:="GetWindowRect")> _
        Private Shared Function GetWindowRect(ByVal hWnd As IntPtr, ByRef lpRect As RECT) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("user32.dll", EntryPoint:="mouse_event")> _
        Private Shared Sub mouse_event(ByVal dwFlags As UInteger, ByVal dx As Integer, ByVal dy As Integer, ByVal dwData As Integer, ByVal dwExtraInfo As UInteger)
        End Sub
    
        <StructLayout(LayoutKind.Sequential)> _
        Private Structure RECT
            Public left As Integer
            Public top As Integer
            Public right As Integer
            Public bottom As Integer
        End Structure
    
        <StructLayout(LayoutKind.Sequential)> _
            Private Structure TVITEM
            Public mask As Integer
            Public hItem As IntPtr
            Public State As Integer
            Public stateMask As Integer
            Public pszText As IntPtr
            Public cchTextMax As Integer
            Public iImage As Integer
            Public iSelectedImage As Integer
            Public cChildren As Integer
            Public lParam As IntPtr
        End Structure
    
        Private Const TV_FIRST As Integer = &H1100
        Private Const TVM_EXPAND As Integer = (TV_FIRST + 2)
        Private Const TVM_GETITEMRECT As Integer = (TV_FIRST + 4)
        Private Const TVM_GETCOUNT As Integer = (TV_FIRST + 5)
        Private Const TVM_GETNEXTITEM As Integer = (TV_FIRST + 10)
        Private Const TVM_SELECTITEM As Integer = (TV_FIRST + 11)
        Private Const TVM_HITTEST As Integer = (TV_FIRST + 17)
        Private Const TVM_ENSUREVISIBLE As Integer = (TV_FIRST + 20)
        Private Const TVM_ENDEDITLABELNOW As Integer = (TV_FIRST + 22)
        Private Const TVM_GETTOOLTIPS As Integer = (TV_FIRST + 25)
        Private Const TVM_GETITEMSTATE As Integer = (TV_FIRST + 39)
        Private Const TVM_MAPACCIDTOHTREEITEM As Integer = (TV_FIRST + 42)
        Private Const TVM_MAPHTREEITEMTOACCID As Integer = (TV_FIRST + 43)
        Private Const TVM_GETITEMW As Integer = (TV_FIRST + 62)
        Private Const TVM_SETITEMW As Integer = (TV_FIRST + 63)
        Private Const TVM_EDITLABELW As Integer = (TV_FIRST + 65)
    
        Private Const TVGN_ROOT As Integer = &H0
        Private Const TVGN_NEXT As Integer = &H1
        Private Const TVGN_PREVIOUS As Integer = &H2
        Private Const TVGN_PARENT As Integer = &H3
        Private Const TVGN_CHILD As Integer = &H4
        Private Const TVGN_CARET As Integer = &H9
    
        Private Const TVE_COLLAPSE As Integer = &H1
        Private Const TVE_EXPAND As Integer = &H2
    
        Private Const TVIF_TEXT As Integer = &H1
        Private Const TVIF_IMAGE As Integer = &H2
        Private Const TVIF_STATE As Integer = &H8
        Private Const TVIF_CHILDREN As Integer = &H40
    
        Private Const TVIS_SELECTED As Integer = &H2
        Private Const TVIS_EXPANDED As Integer = &H20
        Private Const TVIS_STATEIMAGEMASK As Integer = &HF000
    
        Private Const MEM_COMMIT As UInteger = &H1000
        Private Const MEM_RELEASE As UInteger = &H8000
        Private Const PAGE_READWRITE As UInteger = &H4
    
        Private Const PROCESS_VM_READ As UInteger = &H10
        Private Const PROCESS_VM_WRITE As UInteger = &H20
        Private Const PROCESS_VM_OPERATION As UInteger = &H8
    
        Private Const MOUSEEVENTF_LEFTDOWN As Integer = &H2
        Private Const MOUSEEVENTF_LEFTUP As Integer = &H4
        Private Const MOUSEEVENTF_RIGHTDOWN As Integer = &H8
        Private Const MOUSEEVENTF_RIGHTUP As Integer = &H10
    
    End Class
    

     Here is the above example showing that it expands the nodes so that the 2nd child node of the 3rd root node is visible and then double clicks the left mouse button on it which expands the child node. Then it returns the mouse back to the button on my form. Then when i click the button a second time it does the same thing except it closes the child node when it is double clicked this time.

     

     This does seem like a lot of work just to click on a node in a 3rd party window. Perhaps it would be easier to just manually click it instead of going through all of this.  8)


    If you say it can`t be done then i`ll try it

    Professor professional I have a question how can I get all  child nodes in textbox?
    Wednesday, September 3, 2014 1:49 PM
  • Hi,

     Doing this is kind of similar to getting the items rectangle area. You need to read and write to the processes`s memory to retrieve the text of each node using the TVITEM structure. Here is an example of getting each child nodes text of the 3rd root node.

    Imports System.Runtime.InteropServices
    Imports System.Text
    
    Public Class Form1
        Private TVList As New List(Of IntPtr)
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim hParent As IntPtr = FindWindowW(Nothing, "form1") 'Get the handle of the Parent Window that the TreeView is on
            If hParent <> IntPtr.Zero Then
                Dim hTv As IntPtr = GetTreeviewHandlesFrom(hParent)(0) 'Get the handle of the 1st Treeview on the Parent Window
                If hTv <> IntPtr.Zero Then
                    Dim hRootNode As IntPtr = GetRootNodeHandle(hTv, 2) 'Get the handle of the 3rd root node (2)
                    If hRootNode <> IntPtr.Zero Then
                        'Call the GetAllChildNodeText function which returns a string array of all the child
                        'nodes texts and assing the array to the lines property of the textbox
                        TextBox1.Lines = GetAllChildNodeText(hTv, hRootNode)
                    End If
                End If
            End If
        End Sub
    
        Private Function GetAllChildNodeText(ByVal tvHandle As IntPtr, ByVal hParentNode As IntPtr) As String()
            Dim MemTextPointer, MemTVItemPointer, TextPointer, TVItemPointer As IntPtr
            Dim nTxt As New List(Of String)
            Dim NodeText As String
            Dim NodeTextLength As Integer
            Dim hChildNode As IntPtr = SendMessageW(tvHandle, TVM_GETNEXTITEM, TVGN_CHILD, hParentNode)
    
            Dim procId As Integer = Nothing
            GetWindowThreadProcessId(tvHandle, procId)
            Dim hProc As IntPtr = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, False, procId)
    
            While hChildNode <> IntPtr.Zero
                NodeText = Space(256)
                NodeTextLength = NodeText.Length
    
                TextPointer = Marshal.StringToHGlobalUni(NodeText)
                MemTextPointer = VirtualAllocEx(hProc, IntPtr.Zero, NodeTextLength, MEM_COMMIT, PAGE_READWRITE)
                WriteProcessMemory(hProc, MemTextPointer, TextPointer, NodeTextLength, 0)
    
                Dim tvi As TVITEM
                tvi.mask = TVIF_TEXT
                tvi.hItem = hChildNode
                tvi.pszText = MemTextPointer
                tvi.cchTextMax = NodeTextLength
                Dim nSizeTVITEM As Integer = Marshal.SizeOf(tvi)
                MemTVItemPointer = VirtualAllocEx(hProc, IntPtr.Zero, nSizeTVITEM, MEM_COMMIT, PAGE_READWRITE)
                TVItemPointer = Marshal.AllocHGlobal(nSizeTVITEM)
                Marshal.StructureToPtr(tvi, TVItemPointer, True)
                WriteProcessMemory(hProc, MemTVItemPointer, TVItemPointer, nSizeTVITEM, 0)
    
                SendMessageW(tvHandle, TVM_GETITEMW, 0, MemTVItemPointer)
    
                ReadProcessMemory(hProc, MemTextPointer, TextPointer, NodeTextLength, 0)
                NodeText = Marshal.PtrToStringUni(TextPointer)
                nTxt.Add(NodeText)
    
                Marshal.FreeHGlobal(TVItemPointer)
    
                hChildNode = SendMessageW(tvHandle, TVM_GETNEXTITEM, TVGN_NEXT, hChildNode)
            End While
    
            VirtualFreeEx(hProc, MemTVItemPointer, 0, MEM_RELEASE)
            VirtualFreeEx(hProc, MemTextPointer, 0, MEM_RELEASE)
            CloseHandle(hProc)
    
            Return nTxt.ToArray
        End Function
    
        Private Function GetRootNodeHandle(ByVal tvHandle As IntPtr, ByVal NodeIndex As Integer) As IntPtr
            Dim hNode As IntPtr = SendMessageW(tvHandle, TVM_GETNEXTITEM, TVGN_ROOT, IntPtr.Zero) 'Get 1st root node handle
            'Iterate to the node wanted if (NodeIndex) is not not the 1st node (0) and get its handle
            For i As Integer = 1 To NodeIndex
                hNode = SendMessageW(tvHandle, TVM_GETNEXTITEM, TVGN_NEXT, hNode)
            Next
            Return hNode 'Return the root node handle
        End Function
    
        Private Function GetChildNodeHandle(ByVal tvHandle As IntPtr, ByVal hParentNode As IntPtr, ByVal ChildNodeIndex As Integer) As IntPtr
            Dim hChildNode As IntPtr = SendMessageW(tvHandle, TVM_GETNEXTITEM, TVGN_CHILD, hParentNode) 'Get the 1st child node
            'Iterate to the child node wanted if (ChildNodeIndex) is not not the 1st node (0) and get its handle
            For i As Integer = 1 To ChildNodeIndex
                hChildNode = SendMessageW(tvHandle, TVM_GETNEXTITEM, TVGN_NEXT, hChildNode)
            Next
            Return hChildNode 'Return the child node handle
        End Function
    
        Private Function GetTreeviewHandlesFrom(ByVal hwnd As IntPtr) As List(Of IntPtr)
            TVList.Clear()
            EnumChildWindows(hwnd, AddressOf EnumChildWindowProc, 0)
            Return TVList
        End Function
    
        Private Function EnumChildWindowProc(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Integer
            Dim cn As New StringBuilder(255)
            GetClassNameW(hwnd, cn, 255)
            If cn.ToString.ToLower.ToLower.Contains("systreeview32") Then 'Make sure the child window is a Treeview before adding its handle to the List
                TVList.Add(hwnd)
            End If
            Return 1
        End Function
    
        <DllImport("kernel32.dll", EntryPoint:="WriteProcessMemory")> _
        Private Shared Function WriteProcessMemory(ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByVal lpBuffer As IntPtr, ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("kernel32.dll", EntryPoint:="ReadProcessMemory")> _
        Private Shared Function ReadProcessMemory(ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByVal lpBuffer As IntPtr, ByVal nSize As Integer, ByRef lpNumberOfBytesRead As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("kernel32.dll", EntryPoint:="OpenProcess")> _
        Private Shared Function OpenProcess(ByVal dwDesiredAccess As UInteger, <MarshalAs(UnmanagedType.Bool)> ByVal bInheritHandle As Boolean, ByVal dwProcessId As Integer) As IntPtr
        End Function
    
        <DllImport("kernel32.dll", EntryPoint:="CloseHandle")> _
        Private Shared Function CloseHandle(ByVal hObject As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("kernel32.dll", EntryPoint:="VirtualAllocEx")> _
        Private Shared Function VirtualAllocEx(ByVal hProcess As IntPtr, ByVal lpAddress As IntPtr, ByVal dwSize As Integer, ByVal flAllocationType As UInteger, ByVal flProtect As UInteger) As IntPtr
        End Function
    
        <DllImportAttribute("kernel32.dll", EntryPoint:="VirtualFreeEx")> _
        Private Shared Function VirtualFreeEx(ByVal hProcess As IntPtr, ByVal lpAddress As IntPtr, ByVal dwSize As UInteger, ByVal dwFreeType As UInteger) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("user32.dll", EntryPoint:="FindWindowW")> _
        Private Shared Function FindWindowW(<MarshalAs(UnmanagedType.LPTStr)> ByVal lpClassName As String, <MarshalAs(UnmanagedType.LPTStr)> ByVal lpWindowName As String) As IntPtr
        End Function
    
        <DllImport("user32.dll", EntryPoint:="GetClassNameW")> _
        Private Shared Function GetClassNameW(ByVal hWnd As IntPtr, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpClassName As System.Text.StringBuilder, ByVal nMaxCount As Integer) As Integer
        End Function
    
        <UnmanagedFunctionPointer(CallingConvention.StdCall)> _
        Private Delegate Function EnumCallBackDelegate(ByVal hwnd As IntPtr, ByVal lParam As IntPtr) As Integer
    
        <DllImport("user32.dll", EntryPoint:="EnumChildWindows")> _
        Private Shared Function EnumChildWindows(ByVal hWndParent As IntPtr, ByVal lpEnumFunc As EnumCallBackDelegate, ByVal lParam As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function
    
        <DllImport("user32.dll", EntryPoint:="GetWindowThreadProcessId")> _
        Private Shared Function GetWindowThreadProcessId(ByVal hWnd As IntPtr, ByRef lpdwProcessId As Integer) As Integer
        End Function
    
        <DllImport("user32.dll", EntryPoint:="SendMessageW")> _
        Private Shared Function SendMessageW(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As Integer, ByVal lParam As IntPtr) As IntPtr
        End Function
    
        <StructLayout(LayoutKind.Sequential)> _
            Private Structure TVITEM
            Public mask As Integer
            Public hItem As IntPtr
            Public State As Integer
            Public stateMask As Integer
            Public pszText As IntPtr
            Public cchTextMax As Integer
            Public iImage As Integer
            Public iSelectedImage As Integer
            Public cChildren As Integer
            Public lParam As IntPtr
        End Structure
    
        Private Const TV_FIRST As Integer = &H1100
        Private Const TVM_EXPAND As Integer = (TV_FIRST + 2)
        Private Const TVM_GETITEMRECT As Integer = (TV_FIRST + 4)
        Private Const TVM_GETCOUNT As Integer = (TV_FIRST + 5)
        Private Const TVM_GETNEXTITEM As Integer = (TV_FIRST + 10)
        Private Const TVM_SELECTITEM As Integer = (TV_FIRST + 11)
        Private Const TVM_HITTEST As Integer = (TV_FIRST + 17)
        Private Const TVM_ENSUREVISIBLE As Integer = (TV_FIRST + 20)
        Private Const TVM_ENDEDITLABELNOW As Integer = (TV_FIRST + 22)
        Private Const TVM_GETTOOLTIPS As Integer = (TV_FIRST + 25)
        Private Const TVM_GETITEMSTATE As Integer = (TV_FIRST + 39)
        Private Const TVM_MAPACCIDTOHTREEITEM As Integer = (TV_FIRST + 42)
        Private Const TVM_MAPHTREEITEMTOACCID As Integer = (TV_FIRST + 43)
        Private Const TVM_GETITEMW As Integer = (TV_FIRST + 62)
        Private Const TVM_SETITEMW As Integer = (TV_FIRST + 63)
        Private Const TVM_EDITLABELW As Integer = (TV_FIRST + 65)
    
        Private Const TVGN_ROOT As Integer = &H0
        Private Const TVGN_NEXT As Integer = &H1
        Private Const TVGN_PREVIOUS As Integer = &H2
        Private Const TVGN_PARENT As Integer = &H3
        Private Const TVGN_CHILD As Integer = &H4
        Private Const TVGN_CARET As Integer = &H9
    
        Private Const TVE_COLLAPSE As Integer = &H1
        Private Const TVE_EXPAND As Integer = &H2
    
        Private Const TVIF_TEXT As Integer = &H1
        Private Const TVIF_IMAGE As Integer = &H2
        Private Const TVIF_STATE As Integer = &H8
        Private Const TVIF_CHILDREN As Integer = &H40
    
        Private Const TVIS_SELECTED As Integer = &H2
        Private Const TVIS_EXPANDED As Integer = &H20
        Private Const TVIS_STATEIMAGEMASK As Integer = &HF000
    
        Private Const MEM_COMMIT As UInteger = &H1000
        Private Const MEM_RELEASE As UInteger = &H8000
        Private Const PAGE_READWRITE As UInteger = &H4
    
        Private Const PROCESS_VM_READ As UInteger = &H10
        Private Const PROCESS_VM_WRITE As UInteger = &H20
        Private Const PROCESS_VM_OPERATION As UInteger = &H8
    End Class
    
    
     

     

     You will need to study all these examples i have written for you and do some experimenting so you can start figuring this stuff out. You can get a lot of information from the msdn documents on these Functions and Structures and by searching the internet for examples. I know there is not a lot of examples and the msdn documents can be confusing or missing info because, that is how i learned to do these things but, nothing is easy until you learn it.   8)


    If you say it can`t be done then i`ll try it

    • Marked as answer by HeroCodec Wednesday, September 3, 2014 3:38 PM
    Wednesday, September 3, 2014 3:10 PM
  • Hi,

    I tried getting the bounding rectangle of treeitem from an external process. 
    I followed the above given code itself but no help. 

    Here the code which I wrote.  Can you please look in to it and let me know what went wrong here. 

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Windows.Forms;
    
    namespace GetBoundingRect
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                IntPtr hParent = FindWindowW(null, "VB6TreeView");
    
                IntPtr HwndOfMYWindow = GetTreeviewHandlesFrom(hParent)[0];
    
                IntPtr hTv = HwndOfMYWindow;
                if (hTv != IntPtr.Zero)
                {
                    IntPtr hRootNode = GetRootNodeHandle(hTv);
                    if (hRootNode != IntPtr.Zero)
                    {
                        SendMessageW(hTv, TVM_EXPAND, TVE_EXPAND, hRootNode);
                        IntPtr hChildNode = GetChildNodeHandle(hTv, hRootNode, 1);
                        if (hChildNode != IntPtr.Zero)
                        {
                            GetRectangleOFThisTreeNode(HwndOfMYWindow, hRootNode);
                        }
                    }
                }
            }
    
            [DllImport("user32.dll", EntryPoint = "FindWindowW")]
            private static extern IntPtr FindWindowW([MarshalAs(UnmanagedType.LPTStr)] string lpClassName, [MarshalAs(UnmanagedType.LPTStr)] string lpWindowName);
    
            [DllImport("user32.dll", EntryPoint = "SendMessageW")]
            private static extern IntPtr SendMessageW(IntPtr hWnd, uint Msg, int wParam, IntPtr lParam);
    
            [DllImport("user32.dll", EntryPoint = "EnumChildWindows")]
            [return: MarshalAs(UnmanagedType.Bool)]
            private static extern bool EnumChildWindows(IntPtr hWndParent, EnumCallBackDelegate lpEnumFunc, int lParam);
    
            [UnmanagedFunctionPointer(CallingConvention.StdCall)]
            private delegate int EnumCallBackDelegate(IntPtr hwnd, IntPtr lParam);
    
            [DllImport("user32.dll", EntryPoint = "GetClassNameW")]
            private static extern int GetClassNameW(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)] System.Text.StringBuilder lpClassName, int nMaxCount);
    
            private const int TV_FIRST = 0x1100;
    
            private const int TVM_EXPAND = (TV_FIRST + 2);
            private const int TVE_EXPAND = 0x2;
            private const int TVM_GETNEXTITEM = (TV_FIRST + 10);
            private const int TVGN_CHILD = 0x4;
            private const int TVGN_NEXT = 0x1;
            private const int TVGN_ROOT = 0x0;
    
            private List<IntPtr> TVList = new List<IntPtr>();
    
            [StructLayout(LayoutKind.Sequential)]
            private struct RECT
            {
                public int left;
                public int top;
                public int right;
                public int bottom;
            }
    
            private const uint PROCESS_VM_READ = 0x10;
            private const uint PROCESS_VM_WRITE = 0x20;
            private const uint PROCESS_VM_OPERATION = 0x8;
            private const uint MEM_COMMIT = 0x1000;
            private const uint MEM_RELEASE = 0x8000;
            private const uint PAGE_READWRITE = 0x4;
            private const int TVM_GETITEMRECT = (TV_FIRST + 4);
    
            [DllImport("user32.dll", EntryPoint = "GetWindowThreadProcessId")]
            private static extern int GetWindowThreadProcessId(IntPtr hWnd, ref int lpdwProcessId);
            
            [DllImport("kernel32.dll", EntryPoint = "OpenProcess")]
            private static extern IntPtr OpenProcess(uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId);
    
            [DllImport("kernel32.dll", EntryPoint = "VirtualAllocEx")]
            private static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, uint flAllocationType, uint flProtect);
    
            [DllImport("kernel32.dll", EntryPoint = "WriteProcessMemory")]
            [return: MarshalAs(UnmanagedType.Bool)]
            private static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, ref RECT lpBuffer, int nSize, ref int lpNumberOfBytesWritten);
    
            [DllImport("kernel32.dll", EntryPoint = "ReadProcessMemory")]
            [return: MarshalAs(UnmanagedType.Bool)]
            private static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, ref RECT lpBuffer, int nSize, ref int lpNumberOfBytesRead);
    
            [DllImportAttribute("kernel32.dll", EntryPoint = "VirtualFreeEx")]
            [return: MarshalAs(UnmanagedType.Bool)]
            private static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint dwFreeType);
    
            [DllImport("kernel32.dll", EntryPoint = "CloseHandle")]
            [return: MarshalAs(UnmanagedType.Bool)]
            private static extern bool CloseHandle(IntPtr hObject);
    
            [DllImport("user32.dll", EntryPoint = "GetWindowRect")]
            [return: MarshalAs(UnmanagedType.Bool)]
            private static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
    
            private void   GetRectangleOFThisTreeNode(IntPtr treeViewHwnd, IntPtr TreeItemHwnd)
            {
                int processId = 0;
                GetWindowThreadProcessId(treeViewHwnd, ref processId);
    
                IntPtr HProc = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, false, processId);
    
                RECT nRect = new RECT();
                nRect.left = TreeItemHwnd.ToInt32();
    
    
                IntPtr tvNodeRectPtr = VirtualAllocEx(HProc, IntPtr.Zero, Marshal.SizeOf(nRect), MEM_COMMIT, PAGE_READWRITE);
                int aRefRequired = 0;
                WriteProcessMemory(HProc, tvNodeRectPtr,ref nRect, Marshal.SizeOf(nRect), ref aRefRequired );
    
                SendMessageW(treeViewHwnd, TVM_GETITEMRECT, 1, tvNodeRectPtr);
    
                int anotherRef = 0;
    
                ReadProcessMemory(HProc, tvNodeRectPtr,ref nRect, Marshal.SizeOf(nRect), ref anotherRef);
    
                VirtualFreeEx(HProc, tvNodeRectPtr, 0, MEM_RELEASE);
                CloseHandle(HProc);
    
                RECT tvRect = new RECT();
                GetWindowRect(treeViewHwnd,ref  tvRect);
            }
    
    
            private IntPtr GetChildNodeHandle(IntPtr tvHandle, IntPtr hParentNode, int ChildNodeIndex)
            {
                IntPtr hChildNode = SendMessageW(tvHandle, TVM_GETNEXTITEM, TVGN_CHILD, hParentNode);
    
                for (int i = 1; i <= ChildNodeIndex; i++)
                {
                    hChildNode = SendMessageW(tvHandle, TVM_GETNEXTITEM, TVGN_NEXT, hChildNode);
                }
                return hChildNode;
            }
    
            private IntPtr GetRootNodeHandle(IntPtr tvHandle)
            {
                IntPtr hNode = SendMessageW(tvHandle, TVM_GETNEXTITEM, TVGN_ROOT, IntPtr.Zero);
    
                for (int i = 1; i <= 3; i++)
                {
                    hNode = SendMessageW(tvHandle, TVM_GETNEXTITEM, TVGN_NEXT, hNode);
                }
                return hNode;
            }
    
            private IntPtr[] GetTreeviewHandlesFrom(IntPtr hwnd)
            {
                TVList.Clear();
                EnumChildWindows(hwnd, EnumChildWindowProc, 0);
                return TVList.ToArray();
            }
    
            private int EnumChildWindowProc(IntPtr hwnd, IntPtr lParam)
            {
                StringBuilder cn = new StringBuilder(255);
                GetClassNameW(hwnd, cn, 255);
                if (cn.ToString().Contains("TreeView20WndClass"))
                {
                    TVList.Add(hwnd);
                }
                return 1;
            }
        }
    }
    

    In my Button click event am trying to get Hwnd of Tree View and Treenode of another application. I am able to get both Hwnds but not the rectangle. 

    Need your help in achieving this. 

    Thursday, August 25, 2016 8:45 AM
  • In my Button click event am trying to get Hwnd of Tree View and Treenode of another application. I am able to get both Hwnds but not the rectangle. 


    Need your help in achieving this. 

     How do you know you are not getting the RECT of the node,  did you check the  nRect  values in your GetRectangleOFThisTreeNode sub somehow?  Does the node expand when you hit the button on your app?  Also,  did you try running your application`s exe file as an administrator by right clicking on the exe and choosing "Run As Administrator"?

     Just so you are aware,  you are not suppose to post and ask about C# code in the VB.Net forum.


    If you say it can`t be done then i`ll try it

    • Edited by IronRazerz Thursday, August 25, 2016 11:36 PM
    Thursday, August 25, 2016 11:14 PM