Page 1 of 1

(Explorer)TreeGadget MS internal structure

Posted: Wed Aug 16, 2006 11:09 pm
by sverson
Code updated For 5.20+


Looking for a way to step through ExplorerList elements I found this MS internal structure...
-----------------
Brad's VB-32 Programs & Samples
btmtz.mvps.org - TVItemData: Treeview item data (or how undocumented can you get?)
-----------------

Here some code to play with...

Code: Select all

;/ Some extra info on (Explorer)TreeGadgets
;/ sverson 2006-08-16 PB4 final

Structure TREE_ITEM  ;/ MS internal TreeItem structure (see http://btmtz.mvps.org [TVITEM1Data])
  hitemParent.l      ;/ handle of the item's parent, can be 0 (root's parent is a dummy item, whose only valid member is the hitemChild, the root itself)
  hitemNextSibling.l ;/ handle of the item's Next sibling, can be 0
  hitemChild.l       ;/ handle of the item's first child, can be 0
  lpszText.l         ;/ pointer to the item's text, allocated in DWORD chunks, can be LPSTR_TEXTCALLBACK, is Unicode on NT.
  wState.w           ;/ item's state flags, 1st byte is state, low nibble of 2nd byte is overlay image index, high nibble of 2nd byte is state image index
  wImage.w           ;/ normal icon imagelist index, can be I_IMAGECALLBACK (&HFFFF)
  wSelectedImage.w   ;/ selected icon imagelist index, can be I_IMAGECALLBACK (&HFFFF)
  cxItem.w           ;/ item's label width in pixels (TVM_GETITEMRECT/TRUE)
  wIndex.w           ;/ visible item's 0-based physical tree Position, is -1 If in collapsed parent, can change
  bLevel.b           ;/ item's 0-based hierarchical level in the tree
  bChildren.b        ;/ TVITEM1.cChildren, can't be I_CHILDRENCALLBACK (?)
  lParam.l           ;/ TVITEM1.lParam, usually points to something internally allocated
  ;dwID.l             ;/ always 1
EndStructure
Structure TREE_ITEM5  ;/ MS internal TreeItem structure (see http://btmtz.mvps.org [TVITEM1Data])
  ;{/ Microsoft, in its complete freedom to break the undocumented, has done just that.
  ;/ Begining with Comctl32.dll v5.xx, the TREEITEM structure above has been changed,
  ;/ not by much, but just enough to break the apps of folks who decided to use it. The
  ;/ lParam  member has been moved up, from below the bChildren member, to below the
  ;}/ lpszText member. The dwID (was dwIDBit) member's Value has also been changed.
  hitemParent.l      ;/ handle of the item's parent, can be 0 (root's parent is a dummy item, whose only valid member is the hitemChild, the root itself)
  hitemNextSibling.l ;/ handle of the item's Next sibling, can be 0
  hitemChild.l       ;/ handle of the item's first child, can be 0
  lpszText.l         ;/ pointer to the item's Unicode text, allocated in DWORD chunks, can be LPSTR_TEXTCALLBACK.
  lParam.l           ;/ TVITEM1.lParam, usually points to something internally allocated
  wState.w           ;/ item's state flags, 1st byte is state, low nibble of 2nd byte is overlay image index, high nibble of 2nd byte is state image index
  wImage.w           ;/ normal icon imagelist index, can be I_IMAGECALLBACK (&HFFFF)
  wSelectedImage.w   ;/ selected icon imagelist index, can be I_IMAGECALLBACK (&HFFFF)
  cxItem.w           ;/ item's label width in pixels (TVM_GETITEMRECT/TRUE)
  wIndex.w           ;/ visible item's 0-based physical tree Position, is -1 If in collapsed parent, can change
  bLevel.b           ;/ item's 0-based hierarchical level in the tree
  bChildren.b        ;/ TVITEM1.cChildren, can't be I_CHILDRENCALLBACK (?)
  dwID.l             ;/ always &HABCD0001 ?
EndStructure
Structure TVITEM1
  mask.l
  hItem.l
  state.l
  stateMask.l
  pszText.l
  cchTextMax.l
  iImage.l
  iSelectedImage.l
  cChildren.l
  lParam.l
EndStructure

Global MainWindowEvent.l, MainGadgetID.l, LastlParam.l=0
Global ExplorerTreeNo.l, ExplorerTreeID.l, ListIconNo.l, ListIconID.l, SplitterNo.l

Procedure TreeViewSetCheckBox(tvGadgetNo.l) ;/ Adds CheckBoxes to a TreeView
  #TVS_CHECKBOXES = $100
  Protected tvGadgetID.l, tvGadgetStyles.l
  tvGadgetID     = GadgetID(tvGadgetNo)
  tvGadgetStyles = GetWindowLong_(tvGadgetID,#GWL_STYLE) | #TVS_CHECKBOXES
  SetWindowLong_(tvGadgetID,#GWL_STYLE,tvGadgetStyles)
EndProcedure

Procedure AddInfoRow(*TVITEM1ID.TREE_ITEM5,Level.l,iType.s) ;/ Display TVITEM1Info (TREE_ITEM)
  Protected tviSelf.s, tviParent.s, tviNextSibling.s, tviFirstChild.s, tviText.s, tviState.s, tviImage.s
  Protected tviSelImage.s, tviLabelWidth.s, tviIndex.s, tviLevel.s, tviChildren.s, tviLparam.s
  Protected InfoLine.s
  tviSelf        = "$"+RSet(Hex(*TVITEM1ID),8,"0")
  tviParent      = "$"+RSet(Hex(*TVITEM1ID\hitemParent),8,"0")      ;/ handle of the item's parent, can be 0 (root's parent is a dummy item, whose only valid member is the hitemChild, the root itself)
  tviNextSibling = "$"+RSet(Hex(*TVITEM1ID\hitemNextSibling),8,"0") ;/ handle of the item's Next sibling, can be 0
  tviFirstChild  = "$"+RSet(Hex(*TVITEM1ID\hitemChild),8,"0")       ;/ handle of the item's first child, can be 0
  tviText        = PeekS(*TVITEM1ID\lpszText,-1,#PB_Unicode)        ;/ (pointer to) the item's text, allocated in DWORD chunks, can be LPSTR_TEXTCALLBACK, is Unicode on NT.
  tviState       = "%"+RSet(Bin(*TVITEM1ID\wState),16,"0")          ;/ item's state flags, 1st byte is state, low nibble of 2nd byte is overlay image index, high nibble of 2nd byte is state image index
  tviImage       = "%"+RSet(Bin(*TVITEM1ID\wImage),16,"0")          ;/ normal icon imagelist index, can be I_IMAGECALLBACK (&HFFFF)
  tviSelImage    = "%"+RSet(Bin(*TVITEM1ID\wSelectedImage),16,"0")  ;/ selected icon imagelist index, can be I_IMAGECALLBACK (&HFFFF)
  tviLabelWidth  = Str(*TVITEM1ID\cxItem)+" px"                     ;/ item's label width in pixels (TVM_GETITEMRECT/TRUE)
  tviIndex       = "%"+RSet(Bin(*TVITEM1ID\wIndex),16,"0")          ;/ visible item's 0-based physical tree Position, is -1 If in collapsed parent, can change
  tviLevel       = Str(*TVITEM1ID\bLevel)                           ;/ item's 0-based hierarchical level in the tree
  tviChildren    = Str(*TVITEM1ID\bChildren)                        ;/ TVITEM1.cChildren, can't be I_CHILDRENCALLBACK (?)
  tviLparam      = "$"+RSet(Hex(*TVITEM1ID\lParam),8,"0")           ;/ TVITEM1.lParam, usually points to something internally allocated
  
  InfoLine = Str(Level)+"/"+tviLevel+Chr(10)
  InfoLine + iType+" "+Chr(10)
  InfoLine + tviSelf+Chr(10)
  InfoLine + tviText+Chr(10)
  InfoLine + tviParent+Chr(10)
  InfoLine + tviNextSibling+Chr(10)
  InfoLine + tviFirstChild+Chr(10)
  InfoLine + tviState+Chr(10)
  InfoLine + tviIndex+Chr(10)
  InfoLine + tviImage+Chr(10)
  InfoLine + tviSelImage+Chr(10)
  InfoLine + tviLparam+Chr(10)
  InfoLine + tviChildren+Chr(10)
  InfoLine + tviLabelWidth+Chr(10)
  AddGadgetItem(ListIconNo,-1,InfoLine)
EndProcedure

Procedure TreeViewDisplay(tvGadgetNo.l) ;/ Display all TreeView elements  (currently in memory)
  Protected tvGadgetID.l, *TVITEM1ID1.TREE_ITEM, *TVITEM1ID2.TREE_ITEM, *TVITEM1ID3.TREE_ITEM, TVITEM1Level.l=0, TVITEM1Count.l, tvAktItem.l
  tvGadgetID = GadgetID(tvGadgetNo)
  TVITEM1Count = SendMessage_(tvGadgetID, #TVM_GETCOUNT, 0,0)
  
  AddGadgetItem(ListIconNo,-1,"TreeView"+Chr(10)+"("+Str(TVITEM1Count)+" elements}")
  *TVITEM1ID1 = SendMessage_(tvGadgetID, #TVM_GETNEXTITEM, #TVGN_ROOT, 0)
  If *TVITEM1ID1 : AddInfoRow(*TVITEM1ID1,TVITEM1Level,"ROOT") : EndIf
  For tvAktItem = 1 To TVITEM1Count
    *TVITEM1ID2 = SendMessage_(tvGadgetID, #TVM_GETNEXTITEM, #TVGN_CHILD, *TVITEM1ID1)
    If *TVITEM1ID2 : TVITEM1Level+1 : AddInfoRow(*TVITEM1ID2,TVITEM1Level,"CHILD") : EndIf
    Repeat
      If *TVITEM1ID2 = #Null
        *TVITEM1ID2 = SendMessage_(tvGadgetID, #TVM_GETNEXTITEM, #TVGN_NEXT, *TVITEM1ID1)
        If *TVITEM1ID2 : AddInfoRow(*TVITEM1ID2,TVITEM1Level,"NEXT") : EndIf
      EndIf
      If *TVITEM1ID2 = #Null
        *TVITEM1ID2 = SendMessage_(tvGadgetID, #TVM_GETNEXTITEM, #TVGN_PARENT, *TVITEM1ID1)
        If *TVITEM1ID2
          *TVITEM1ID3 = SendMessage_(tvGadgetID, #TVM_GETNEXTITEM, #TVGN_NEXT, *TVITEM1ID2)
          TVITEM1Level-1
          If *TVITEM1ID3
            AddInfoRow(*TVITEM1ID3,TVITEM1Level,"PARENT/NEXT")
          EndIf
        EndIf
      EndIf
    Until *TVITEM1ID2 <> #Null
    If *TVITEM1ID3
      *TVITEM1ID1 = *TVITEM1ID3
      *TVITEM1ID3=0
    Else
      *TVITEM1ID1 = *TVITEM1ID2
    EndIf
  Next
EndProcedure

If OpenWindow(0, 0, 0, 800, 500, "(Explorer)TreeGadget - Infos", #PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_SizeGadget|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget)
  ExplorerTreeNo = ExplorerTreeGadget(#PB_Any,0,0,0,0,"",#PB_Explorer_NoFiles)
  ExplorerTreeID = GadgetID(ExplorerTreeNo)
  ListIconNo     = ListIconGadget(#PB_Any,0,0,0,0,"Level",0,#PB_ListIcon_FullRowSelect);|#LVS_NOCOLUMNHEADER)
  ListIconID     = GadgetID(ListIconNo)
  SplitterNo     = SplitterGadget(#PB_Any,5,5,WindowWidth(0)-10,WindowHeight(0)-10,ExplorerTreeNo,ListIconNo,#PB_Splitter_Vertical)
  AddGadgetColumn(ListIconNo,1,"#TVGN_",0) : AddGadgetColumn(ListIconNo,2,"Self",0) : AddGadgetColumn(ListIconNo,3,"Text",0)
  AddGadgetColumn(ListIconNo,4,"Parent",0) : AddGadgetColumn(ListIconNo,5,"NextSibling",0) : AddGadgetColumn(ListIconNo,6,"FirstChild",0)
  AddGadgetColumn(ListIconNo,7,"State",0) : AddGadgetColumn(ListIconNo,8,"Index",0) : AddGadgetColumn(ListIconNo,9,"Image",0)
  AddGadgetColumn(ListIconNo,10,"SelImage",0) : AddGadgetColumn(ListIconNo,11,"lParam",0) : AddGadgetColumn(ListIconNo,12,"Children",0)
  AddGadgetColumn(ListIconNo,13,"LabelWidth",0)
  TreeViewSetCheckBox(ExplorerTreeNo)
  TreeViewDisplay(ExplorerTreeNo)
  For x=0 To 13 : SendMessage_(ListIconID,#LVM_SETCOLUMNWIDTH,x,#LVSCW_AUTOSIZE_USEHEADER) : Next
  Repeat
    MainWindowEvent = WaitWindowEvent()
    Select MainWindowEvent
      Case #WM_SIZE
        ResizeGadget(SplitterNo,#PB_Ignore,#PB_Ignore,(WindowWidth(0)-10),WindowHeight(0)-10)
      Case #PB_Event_Gadget
        MainGadgetID = EventGadget()
        Select MainGadgetID
          Case ExplorerTreeNo
            If LastlParam <> EventlParam()
              LastlParam = EventlParam()
              TreeViewDisplay(ExplorerTreeNo)
            EndIf
        EndSelect
    EndSelect
  Until MainWindowEvent = #PB_Event_CloseWindow
EndIf