Reading TreeView from another program.

Just starting out? Need help? Post your questions and find answers here.
epidemicz
User
User
Posts: 86
Joined: Thu Jan 22, 2009 8:05 am
Location: USA
Contact:

Reading TreeView from another program.

Post by epidemicz »

I would like to read a tree view from another program, in my case I want to read the connected user section of ventrilo. I have gotten all the way down to getting the window handle of the treeview but from there I'm kinda stumped. I've found a few example across the net which I'm trying to marry together but I'm really kinda new at PB here.

This is what I found specific to reading the ventrilo treeview: clicky here

This is something I've found specifically regarding PB code taking to TreeViews: Clicky here

However, the wrapper seems to be using some kind of pointer to a cTreeViewOBJ, whereas I am trying to pass it a window handle.

Here's my code if anyone is interested:

Code: Select all

IncludeFile "ooptreeview.pbi"

#MAX_TEXT_LENGTH = 100

Procedure ExtractTreeData(hwndTreeView)
  hCurrentItem.l
  hPrevItem.l
  treeitem.TVITEM
  blah.c
  
  hCurrentItem = TreeView_GetFirstVisible(hwndTreeView)
  
  If hCurrentItem = #Null
    ProcedureReturn #False
  EndIf
  
  While  hPrevItem <> hCurrentItem
    FreeMemory(@treeitem)
    treeitem\mask = #TVIF_IMAGE | #TVIF_TEXT
    treeitem\hItem = hCurrentItem
    treeitem\cchTextMax = 100
    treeitem\pszText = tmptext
    TreeView_GetItem(hwndTreeView, @treeitem)
    ;-----------------------------------------
    ;insert code here
    ;treeitem\pszText is the text
    ;treeitem\iImage is the icon index
    ;Other fields are undefinded due to .mask
    
    MessageBox_(hwndMain, treeitem\pszText, "text", 0)
    hPrevItem = hCurrentItem
    hCurrentItem = TreeView_GetNextVisible(hwndTreeView, hCurrentItem)
  Wend
  
  ProcedureReturn #True
EndProcedure


ventText.s = Space(255)
VentriloHWND = FindWindow_(#Null, "Ventrilo")
Debug "VentriloHWND = " + Str(VentriloHWND)
ventTextLen = GetWindowText_(VentriloHWND, @ventText, 255)
Debug "Length = " + Str(ventTextLen)
Debug "Text = " + ventText

ventTreeHWND = FindWindowEx_(VentriloHWND, 0, "SysTreeView32", "Tree2")
Debug "Vent Tree HWND = " + Str(ventTreeHWND)
Any insight on how I can make this work would be greatly appreciated guys. Thanks very much.
Sparkie
PureBatMan Forever
PureBatMan Forever
Posts: 2307
Joined: Tue Feb 10, 2004 3:07 am
Location: Ohio, USA

Post by Sparkie »

This code by klaver should help you...
http://www.purebasic.fr/english/viewtop ... 899#203899
What goes around comes around.

PB 5.21 LTS (x86) - Windows 8.1
epidemicz
User
User
Posts: 86
Joined: Thu Jan 22, 2009 8:05 am
Location: USA
Contact:

Post by epidemicz »

Man, thanks very much this is exactly what I needed.
epidemicz
User
User
Posts: 86
Joined: Thu Jan 22, 2009 8:05 am
Location: USA
Contact:

Post by epidemicz »

Another question, if anyone can help again I'd really appreciate it.

I can get the handle to the image list with SendMessage_(hTreeView, #TVM_GETIMAGELIST, #TVSIL_NORMAL, 0) but when I try to pass that valid imagelist handle to any of the ImageList_ functions (ie ImageList_GetImageCount_()) they all fail/return nulls.

Would I need to read/write to process memory again somehow, if so I not sure I see how I can do it this time around.

My overall goal is to be able to find out who is talking in ventrilo. I believe all I need at this point is to be able to get a valid return from some of the ImageList functions and I should be able to find out the image index of the current one -- I should be able to use that to determine who is queued up.
Sparkie
PureBatMan Forever
PureBatMan Forever
Posts: 2307
Joined: Tue Feb 10, 2004 3:07 am
Location: Ohio, USA

Post by Sparkie »

You're not going to be able to get any imagelist functions to work because GDI objects are confined to the owner process. Does this help you ID the image index?

(code based on that of klaver)

Code: Select all

Global ventTreeHWND
Procedure EnumCallback(hwnd, Value) 
  ClassName$ = Space(64) 
  GetClassName_(hwnd, @ClassName$, 64) 
  If ClassName$ = "SysTreeView32" 
    ventTreeHWND = hwnd 
    ProcedureReturn #False 
  EndIf 
  ProcedureReturn #True 
EndProcedure 

Procedure.l GetItemID(Gadget.l, item.l) 
  Protected hItem.l, hItem2.l 
  hItem = SendMessage_(Gadget, #TVM_GETNEXTITEM, #TVGN_ROOT, 0) 
  For i.l = 0 To item-1 
    hItem2 = SendMessage_(Gadget, #TVM_GETNEXTITEM, #TVGN_CHILD, hItem) 
    Repeat 
      If hItem2 = #Null
        hItem2 = SendMessage_(Gadget, #TVM_GETNEXTITEM, #TVGN_NEXT, hItem)
      EndIf 
      If hItem2 = #Null
        hItem = SendMessage_(Gadget, #TVM_GETNEXTITEM, #TVGN_PARENT, hItem)
      EndIf
    Until hItem2 <> #Null 
    hItem = hItem2 
  Next i 
  ProcedureReturn hItem 
EndProcedure 

Procedure EnumTreeItems(parent, hwndTreeView)
  ;--- Open tree process
  pid.l = 0
  GetWindowThreadProcessId_(parent, @pid)
  If pid
    result + 1
    tvPrc.l = 0
    tvPrc.l = OpenProcess_(#PROCESS_VM_OPERATION | #PROCESS_VM_READ | #PROCESS_VM_WRITE, #False, pid)
    If tvPrc
      result + 1
      ;--- Creat buffer to hold result for reading tree info
      buffSize = SizeOf(TV_ITEM) + 512
      *Buff1 = VirtualAllocEx_(tvPrc, 0, buffSize, #MEM_COMMIT,  #PAGE_READWRITE)
      If *Buff1
        result + 1
      EndIf
    EndIf
  EndIf
  
  ;--- Write tvi\dwMask TBBUTTONINFO to taskbar
  tvi.TV_ITEM
  tvi\mask = #TVIF_TEXT | #TVIF_HANDLE | #TVIF_SELECTEDIMAGE
  tvi\pszText = *Buff1 + SizeOf(TV_ITEM)
  tvi\cchTextMax = 260 
  ;--- Loop through all tree items
  If *Buff1
    itemCount = SendMessage_(hwndTreeView, #TVM_GETCOUNT, 0, 0)-1 
    For i = 0 To itemCount
      tvi\hItem = GetItemID(hwndTreeView, i)
      WriteProcessMemory_(tvPrc, *Buff1, @tvi, buffSize, @result)
      ;--- Get the tree item info
      SendMessage_(hwndTreeView, #TVM_GETITEM, i, *Buff1)
      ;- get the item image info
      ReadProcessMemory_(tvPrc, *Buff1, @tvi, SizeOf(tvi), @result)
      itemText$ = Space(260)
      ;- Get the item text
      ReadProcessMemory_(tvPrc, tvi\pszText, @itemText$, 260, @result)
      AddGadgetItem(0, -1, itemText$ + " ImageID: " + Str(tvi\iSelectedImage))
    Next i
    VirtualFreeEx_(tvPrc, *Buff1, 0, #MEM_RELEASE)
    CloseHandle_(tvPrc) 
  EndIf
EndProcedure

If OpenWindow(0, 0, 0, 700, 500, "Test by Sparkie",  #PB_Window_SizeGadget | #PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_TitleBar)
  EditorGadget(0, 0, 0, 700, 500) 
  ventText.s = Space(255) 
  VentriloHWND = FindWindow_(#Null, "Ventrilo") 
  ventTextLen = GetWindowText_(VentriloHWND, @ventText, 255) 
  ventTreeHWND = FindWindowEx_(VentriloHWND, 0, "SysTreeView32", "Tree2") 
  If VentriloHWND And ventTreeHWND
    EnumTreeItems(VentriloHWND, ventTreeHWND)
  Else
    MessageRequester("Error", "Ventrilo not found", #PB_MessageRequester_Ok | #MB_ICONERROR)
    End
  EndIf
  
  Repeat
    event = WaitWindowEvent()
  Until event = #PB_Event_CloseWindow
EndIf
End
Last edited by Sparkie on Sat Jan 24, 2009 3:41 am, edited 1 time in total.
What goes around comes around.

PB 5.21 LTS (x86) - Windows 8.1
epidemicz
User
User
Posts: 86
Joined: Thu Jan 22, 2009 8:05 am
Location: USA
Contact:

Post by epidemicz »

Sparkie you are the man, thank you very much :D.

I'll be looking and studying this code for a while I think. One thing to note I did have to modify the for loop to use itemCount i think it was for i = 0 to 100 or so and it was hanging me up.

Thanks again man.
Sparkie
PureBatMan Forever
PureBatMan Forever
Posts: 2307
Joined: Tue Feb 10, 2004 3:07 am
Location: Ohio, USA

Post by Sparkie »

You're welcome. :)

I edited and fixed the loop counter. Sorry about that, I was using a count of 10 in my test and forgot to change it back.
What goes around comes around.

PB 5.21 LTS (x86) - Windows 8.1
Post Reply