Page 1 of 2

[SOLVED] Treeview item handle and item index nr (Windows)

Posted: Wed Feb 12, 2025 8:10 pm
by boddhi
Hello,

I'd like to retrieve the item number hovered over (0 to x) of a treeview.
I have this piece of code that gives me the item's handle, but I can't establish a correspondence with the PB index number (like the one returned by GetGadgetState() during a selection).
How can I do this?
Thanks for your help.

Code: Select all

OpenWindow(0,0,0,400,200,"Treeview",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
TreeGadget(0,10,10,380,180)
AddGadgetItem(0,-1,"Item 0",0,0)
AddGadgetItem(0,-1,"Item 1",0,0)
AddGadgetItem(0,-1,"Node (Item 2)"+Str(a),0,0)
AddGadgetItem(0,-1,"Sub-Item 1 (Item 3)",0,1)
AddGadgetItem(0,-1,"Sub-Item 2 (Item 4)",0,1)
AddGadgetItem(0,-1,"Sub-Item 3 (Item 5)",0,1)
;
TVHTI.TV_HITTESTINFO
RECT.RECT
TVITEM.TVITEMEX
OldhItem.i
;
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow:Break
    Case #WM_MOUSEMOVE
      GetCursorPos_(@TVHTI\pt)
      ScreenToClient_(GadgetID(0),@TVHTI\pt)
      SendMessage_(GadgetID(0),#TVM_HITTEST,0,@TVHTI)
      RECT\left=TVHTI\hItem
      If TVHTI\hItem<>OldhItem
        OldhItem=TVHTI\hItem
        Debug "Handle item : "+OldhItem
        If OldhItem<>0
          ; Something else here ?
          SendMessage_(TVHTI\hItem,#TVM_GETITEM,0,@TVITEM)
          Debug "Item : "+TVITEM\hItem
          ; 
        EndIf
      EndIf
  EndSelect 
ForEver
 
 
[EDIT] : To see a fully fonctional code, see this message

Re: Treeview item handle and item index nr (Windows)

Posted: Wed Feb 12, 2025 8:45 pm
by normeus
Maybe use a map to keep track of the handles?

Code: Select all

OpenWindow(0,0,0,400,200,"Treeview",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
TreeGadget(0,10,10,380,180)
AddGadgetItem(0,-1,"Item 0",0,0)
AddGadgetItem(0,-1,"Item 1",0,0)
AddGadgetItem(0,-1,"Node (Item 2)"+Str(a),0,0)
AddGadgetItem(0,-1,"Sub-Item 1 (Item 3)",0,1)
AddGadgetItem(0,-1,"Sub-Item 2 (Item 4)",0,1)
AddGadgetItem(0,-1,"Sub-Item 3 (Item 5)",0,1)
;
NewMap gItem.i()
gItem(Str(GadgetItemID(0, 0)))=0
gItem(Str(GadgetItemID(0, 1)))=1
gItem(Str(GadgetItemID(0, 2)))=2
gItem(Str(GadgetItemID(0, 3)))=3
gItem(Str(GadgetItemID(0, 4)))=4
gItem(Str(GadgetItemID(0, 5)))=5

TVHTI.TV_HITTESTINFO
RECT.RECT
TVITEM.TVITEMEX
OldhItem.i
;
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow:Break
    Case #WM_MOUSEMOVE
      GetCursorPos_(@TVHTI\pt)
      ScreenToClient_(GadgetID(0),@TVHTI\pt)
      SendMessage_(GadgetID(0),#TVM_HITTEST,0,@TVHTI)
      RECT\left=TVHTI\hItem
      If TVHTI\hItem<>OldhItem
        OldhItem=TVHTI\hItem
        Debug "Handle item : "+OldhItem
        Debug "Item from Hamdle: " + gItem(Str(OldhItem))
        If OldhItem<>0
          ; Something else here ?
          SendMessage_(TVHTI\hItem,#TVM_GETITEM,0,@TVITEM)
          ;Debug "Item : "+TVITEM\hItem

          ; 
        EndIf
      EndIf
  EndSelect 
ForEver

Norm.
P.S. slow post

Re: Treeview item handle and item index nr (Windows)

Posted: Wed Feb 12, 2025 8:59 pm
by RASHAD
Hi

Code: Select all

If OpenWindow(0, 0, 0, 400, 600, "TreeGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    TreeGadget(0, 10, 10, 380, 580)
      For a = 0 To 10
        AddGadgetItem (0, -1, "Normal Item "+Str(a), 0, 0)
        AddGadgetItem (0, -1, "Node "+Str(a), 0, 0)
        AddGadgetItem(0, -1, "Sub-Item 1", 0, 1)
        AddGadgetItem(0, -1, "Sub-Item 2", 0, 1)
        AddGadgetItem(0, -1, "Sub-Item 3", 0, 1)
        AddGadgetItem(0, -1, "Sub-Item 4", 0, 1)
        AddGadgetItem (0, -1, "File "+Str(a), 0, 0)
      Next
      tv.TV_HITTESTINFO 
      SetActiveGadget(0)  
Repeat
  Select WaitWindowEvent()
     
    Case #PB_Event_CloseWindow
      Quit = 1
                       
    Case #WM_MOUSEMOVE
      GetCursorPos_(@tv\pt)
      ScreenToClient_(GadgetID(0),@tv\pt)
      h = SendMessage_(GadgetID(0),#TVM_HITTEST,0,tv)
      id = SendMessage_(GadgetID(0),4395 ,h,0) - 1
      SetGadgetState(0 , id)
  EndSelect
Until Quit = 1
EndIf

Re: Treeview item handle and item index nr (Windows)

Posted: Wed Feb 12, 2025 10:17 pm
by HeX0R
in case you are wondering (like me) what that 4395 in RASHADs code might be:

Code: Select all

#TVM_MAPHTREEITEMTOACCID = #TV_FIRST + 43
Debug #TVM_MAPHTREEITEMTOACCID
;https://learn.microsoft.com/en-us/windows/win32/controls/tvm-maphtreeitemtoaccid
;https://github.com/tpn/winsdk-10/blob/master/Include/10.0.16299.0/um/CommCtrl.h

Re: Treeview item handle and item index nr (Windows)

Posted: Wed Feb 12, 2025 10:28 pm
by Piero
I was thinking this thread was a provocation, but then I realized it was just the consuete windows stuff :wink: :mrgreen:

Re: Treeview item handle and item index nr (Windows)

Posted: Wed Feb 12, 2025 10:32 pm
by RASHAD
Hi HeXor :D
You are eight
Yes it's
Lately I just became a bad guy :mrgreen:

Re: Treeview item handle and item index nr (Windows)

Posted: Wed Feb 12, 2025 10:46 pm
by HeX0R
RASHAD wrote: Wed Feb 12, 2025 10:32 pm Hi HeXor :D
You are eight
No, I'm a ten, ask my wife :mrgreen:
(o.k. maybe better not)

Re: Treeview item handle and item index nr (Windows)

Posted: Wed Feb 12, 2025 10:55 pm
by RASHAD
:mrgreen:
Sorry mate
I should use my reading glass all time

Re: Treeview item handle and item index nr (Windows)

Posted: Wed Feb 12, 2025 11:08 pm
by Piero
RASHAD wrote: Wed Feb 12, 2025 10:32 pmLately I just became a bad guy :mrgreen:
Pfft… that's SO easy… didn't you find some other interesting thing to do?

Re: Treeview item handle and item index nr (Windows)

Posted: Thu Feb 13, 2025 10:04 am
by boddhi
Hi,

@normeus
Thanks for your code suggestion. It does the job perfectly, even if I prefer Rashad's solution, which is simpler in terms of coding.

@Rashad (and Hex0r for the precision and links).
Thanks. That's exactly what I needed.

Subsidiary question: Is it technically possible to “grey out” the element hovered over without changing the one already selected?

Re: Treeview item handle and item index nr (Windows)

Posted: Thu Feb 13, 2025 5:48 pm
by Little John
Thanks Rashad! That looks very nice.

Re: Treeview item handle and item index nr (Windows)

Posted: Thu Feb 13, 2025 8:34 pm
by RASHAD
@boddhi
@LJ
Thank you guys
Much appreciated

Treeview item handle and item index nr (Windows)

Posted: Fri Feb 14, 2025 9:42 am
by boddhi
Personal adaptation (for the example) from codes provided by Sparks, Andre, Falsam & Rashad (see links).
1) Tooltip displayed only if label or checkbox is hovered.
2) Multiline if item is a subitem

Code: Select all

; PB links
;   https://www.purebasic.fr/english/viewtopic.php?p=635240#p635240
;   https://www.purebasic.fr/english/viewtopic.php?p=364256#p364256
; External links
;   https://learn.microsoft.com/en-us/windows/win32/controls/tvm-maphtreeitemtoaccid
;   https://github.com/tpn/winsdk-10/blob/master/Include/10.0.16299.0/um/CommCtrl.h
;
EnableExplicit
#TVM_MAPHTREEITEMTOACCID=#TV_FIRST+43
;
#WINDOW=1 ; 1 to make sure everything works properly, but can be any value, of course !
#TREEVVIEW=1
;
Global.i IdToolTip
Define.a Count
;
Procedure.i Fc_ToolTip_Creation(ArgWindowNr.i,ArgGadgetNr.i,ArgTitle.s,ArgText.s,ArgMaxLength.u=0,ArgFlags.u=0)
  Protected.TOOLINFO TOOLINFO
  Protected.i IdToolTip
  
  ArgFlags|#TTS_NOPREFIX ; Other possible options : |#TTS_BALLOON|#TTS_CLOSE
  IdToolTip=CreateWindowEx_(0,"ToolTips_Class32","",ArgFlags,0,0,0,0,WindowID(ArgWindowNr),0,GetModuleHandle_(0),0)
  SendMessage_(IdToolTip,#TTM_SETTIPTEXTCOLOR,GetSysColor_(#COLOR_INFOTEXT),0)
  SendMessage_(IdToolTip,#TTM_SETTIPBKCOLOR,GetSysColor_(#COLOR_INFOBK),0)
  If ArgMaxLength=0:ArgMaxLength=2000:EndIf
  SendMessage_(IdToolTip,#TTM_SETMAXTIPWIDTH,0,ArgMaxLength)
  ;
  With TOOLINFO
    \cbSize=SizeOf(TOOLINFO)
    \uFlags=#TTF_SUBCLASS|#TTF_IDISHWND
    \hWnd=WindowID(ArgWindowNr)
    \uId=GadgetID(ArgGadgetNr)
    \hinst=0
    \lpszText=@ArgText
  EndWith
  SendMessage_(IdToolTip,#TTM_ADDTOOL,0,TOOLINFO)
  SendMessage_(IdToolTip,#TTM_SETDELAYTIME,#TTDT_AUTOPOP,15000)
  If ArgTitle
    SendMessage_(IdToolTip,#TTM_SETTITLE,0,@ArgTitle)
  EndIf
  SendMessage_(IdToolTip,#TTM_UPDATE,0,0)
  ProcedureReturn IdToolTip
EndProcedure
Procedure   Pc_ToolTip_Modification(ArgIdToolTip.i,ArgWindowNr.i,ArgGadgetNr.u,ArgTitle.s,ArgText.s)
  Protected.TOOLINFO TOOLINFO
  
  With TOOLINFO
    \cbSize=SizeOf(TOOLINFO)
    \hWnd=WindowID(ArgWindowNr)
    \uId=GadgetID(ArgGadgetNr)
    \lpszText=@ArgText
  EndWith
  If ArgTitle
    SendMessage_(ArgIdToolTip,#TTM_SETTITLE,0,@ArgTitle)
  EndIf
  SendMessage_(ArgIdToolTip,#TTM_UPDATETIPTEXT,0,TOOLINFO)
EndProcedure
Procedure   Pc_ToolTip_Display(ArgWindowNr.i,ArgGadgetNr.i)
  Protected.TV_HITTESTINFO TVHITTESTINFO
  Protected.i IdItem,Item
  Protected.s String

  GetCursorPos_(@TVHITTESTINFO\pt)
  ScreenToClient_(GadgetID(ArgGadgetNr),@TVHITTESTINFO\pt)
  IdItem=SendMessage_(GadgetID(ArgGadgetNr),#TVM_HITTEST,0,TVHITTESTINFO)
  Item=SendMessage_(GadgetID(ArgGadgetNr),#TVM_MAPHTREEITEMTOACCID,IdItem,0)-1
  ;
  ; Zones de l'item survolées (Item hovered zones) : TVHITTESTINFO\flags
  ; #TVHT_NOWHERE             : 1         -> TVHITTESTINFO\flags&1
  ; #TVHT_ONITEMICON          : 2         -> TVHITTESTINFO\flags>>1&1
  ; #TVHT_ONITEMLABEL         : 4         -> TVHITTESTINFO\flags>>2&1
  ; #TVHT_ONITEMINDENT        : 8         -> TVHITTESTINFO\flags>>3&1
  ; #TVHT_ONITEMBUTTON        : 16        -> TVHITTESTINFO\flags>>4&1
  ; #TVHT_ONITEMRIGHT         : 32        -> TVHITTESTINFO\flags>>5&1
  ; #TVHT_ONITEMSTATEICON     : 64        -> TVHITTESTINFO\flags>>6&1
  ; #TVHT_ONITEM              : 70        -> Bool(TVHITTESTINFO\flags&70=70)
  ; #TVHT_ABOVE               : 256       -> TVHITTESTINFO\flags>>8&1
  ; #TVHT_BELOW               : 512       -> TVHITTESTINFO\flags>>9&1
  ; #TVHT_TORIGHT             : 1024      -> TVHITTESTINFO\flags>>10&1
  ; #TVHT_TOLEFT              : 2048      -> TVHITTESTINFO\flags>>11&1
  ; 
  If Item>=0 And (TVHITTESTINFO\flags>>2&1 Or TVHITTESTINFO\flags>>6&1):String=GetGadgetItemText(ArgGadgetNr,Item):EndIf
  ; Multiline if item sublevel > 0
  If String
    If GetGadgetItemAttribute(ArgGadgetNr,Item,#PB_Tree_SubLevel)>0
      String+#CRLF$+"Subitem level : "+Str(GetGadgetItemAttribute(ArgGadgetNr,Item,#PB_Tree_SubLevel))
    EndIf
  EndIf
  If IdToolTip=0 And Item>=0
    IdToolTip=Fc_ToolTip_Creation(ArgWindowNr,ArgGadgetNr,"Title "+String,String,200)
  Else
    Pc_ToolTip_Modification(IdToolTip,ArgWindowNr,ArgGadgetNr,"Title "+String,String)
  EndIf
  ; SetGadgetState(ArgGadgetNr,Item) ; Select hovered item
EndProcedure
;
If OpenWindow(#WINDOW,0,0,400,600,"TreeGadget",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  TreeGadget(#TREEVVIEW,10,10,380,280,#PB_Tree_CheckBoxes)
  For Count=0 To 1
    AddGadgetItem (#TREEVVIEW,-1,"Normal Item "+Str(Count),0,0)
    AddGadgetItem (#TREEVVIEW,-1,"Node "+Str(Count),0,0)
    AddGadgetItem(#TREEVVIEW,-1,"Sub-Item 1",0,1)
    AddGadgetItem(#TREEVVIEW,-1,"Sub-Item 2",0,1)
    AddGadgetItem(#TREEVVIEW,-1,"Sub-Item 3",0,1)
    AddGadgetItem(#TREEVVIEW,-1,"Sub-Item 4",0,1)
    AddGadgetItem (#TREEVVIEW,-1,"File "+Str(Count),0,0)
  Next
  SetActiveGadget(#TREEVVIEW)
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow:Break
      Case #WM_MOUSEMOVE:Pc_ToolTip_Display(#WINDOW,#TREEVVIEW)
    EndSelect
  ForEver
EndIf

Re: Treeview item handle and item index nr (Windows)

Posted: Sat Feb 15, 2025 9:08 pm
by RASHAD
Hi boddhi
1- Too much coding
2- The ToolTip flicker badly
Next is simple and fancy ToolTip
I hope you will like it

Code: Select all

LoadFont(0,"Georgia",12)
OpenWindow(0,0,0,400,300,"TreeView ToolTips",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)

TreeGadget(0,10,10,380,280)
SetWindowLongPtr_(GadgetID(0), #GWL_STYLE, GetWindowLongPtr_(GadgetID(0), #GWL_STYLE)|#TVS_TRACKSELECT )
For a = 0 To 10
  AddGadgetItem (0, -1, "Normal Item "+Str(a), 0, 0)
  AddGadgetItem (0, -1, "Node "+Str(a), 0, 0)
  AddGadgetItem(0, -1, "Sub-Item 1", 0, 1)
  AddGadgetItem(0, -1, "Sub-Item 2", 0, 1)
  AddGadgetItem(0, -1, "Sub-Item 3", 0, 1)
  AddGadgetItem(0, -1, "Sub-Item 4", 0, 1)
  AddGadgetItem (0, -1, "File "+Str(a), 0, 0)
Next
ttip = CreateWindowEx_(0, "Tooltips_Class32", "", #TTS_ALWAYSTIP|#TTS_BALLOON, 0, 0, 0, 0, 0, 0, 0, 0)
SetWindowTheme_(ttip, @null.w, @null.w)
SendMessage_(ttip,#WM_SETFONT,FontID(0),0)
SendMessage_(ttip,#TTM_SETTIPTEXTCOLOR,$0202FD,0)
SendMessage_(ttip,#TTM_SETTIPBKCOLOR,$DCFFFF,0)
SendMessage_(ttip, #TTM_SETMAXTIPWIDTH, 0, 150)
SendMessage_(ttip, #TTM_SETDELAYTIME, #TTDT_AUTOMATIC,200)

tv.TV_HITTESTINFO

ti.TOOLINFO
ti\cbSize   = SizeOf(ti)
ti\uFlags   = #TTF_IDISHWND | #TTF_SUBCLASS
ti\uId= GadgetID(0)

Repeat
  Select WaitWindowEvent()     
    Case #PB_Event_CloseWindow
      Quit = 1       
      
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 0
      EndSelect         
      
    Case #WM_MOUSEMOVE
      GetCursorPos_(@tv\pt)
      ScreenToClient_(GadgetID(0),@tv\pt)
      item = SendMessage_(GadgetID(0),#TVM_HITTEST,0,tv)
      r.RECT\left = tv\hItem
      SendMessage_(GadgetID(0),#TVM_GETITEMRECT,1,r)
      If tv\pt\x <= r\right And tv\hItem > 0 And tv\hItem <> hItemOld
        SendMessage_(ttip, #TTM_DELTOOL, 0, ti)
        SendMessage_(GadgetID(0),#TVM_SELECTITEM,#TVGN_CARET,tv\hItem)
        SendMessage_(ttip, #TTM_SETDELAYTIME, #TTDT_INITIAL,10)
        Text$ ="ToolTip for Item "+Str(GetGadgetState(0))+" SubLevel : "+Str(GetGadgetItemAttribute(0, GetGadgetState(0), #PB_Tree_SubLevel ))
        ti\lpszText = @Text$
        SendMessage_(ttip, #TTM_ADDTOOL, 0, ti)
        hItemOld = tv\hItem
      EndIf
  EndSelect
Until Quit = 1
End

Re: Treeview item handle and item index nr (Windows)

Posted: Mon Feb 17, 2025 2:36 pm
by boddhi
RASHAD wrote: I hope you will like it
Hi RASCHAD,

Thanks for your code.
However, the code doesn't seem to work properly on my PC under Win10-x64 & PB 6.12-x64 :( .
The tooltip appears “randomly”.
In the screenshot below, I couldn't even get it to display.

Image