AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Finding path to item in treeview [SOLVED]

 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Ask for Help
View previous topic :: View next topic  
Author Message
entropic



Joined: 21 Dec 2008
Posts: 161

PostPosted: Thu Oct 29, 2009 5:24 pm    Post subject: Finding path to item in treeview [SOLVED] Reply with quote

I have a TreeView where you double click an item and it is supposed to return the keystrokes you'd use to get to that item from the root in a collapsed TreeView. It's necessary to get the keystrokes to get to the item because the real TreeView is in another program that uses custom controls that don't respond to any messages, and the only way I've found to navigate it reliably is by sending keystrokes.



In the image above to when you double click "C-2" it should return "{down}{right}{down 3}{right}{down 2}" (the keys you'd press to get to the item from the root of a collapsed treeview) It doesn't matter if it consolidates {down}{down} into {down 2} or anything.

I've been at it for a while and I just can't get it. I've left out my code for ReturnShortcut() below because it doesn't work and I don't want to confuse anyone.

I've also included the function GetItemType(ItemID) which will tell you what type of item ItemID is.

Any help is greatly appreciated!

Code:

Gui, Add, TreeView, R10 gTreeView

P1     := TV_Add("A")
P1C1   := TV_Add("A-1", P1)

P2     := TV_Add("B")
P2C1   := TV_Add("B-1", P2)
P2C2   := TV_Add("B-2", P2)

P3     := TV_Add("C"  , P2)
P3C1   := TV_Add("C-1", P3)
P3C2   := TV_Add("C-2", P3)

P4     := TV_Add("D")
P4C1   := TV_Add("D-1", P4)
P4C2   := TV_Add("D-1", P4)

Gui, Show

return

TreeView:

    If (A_GuiEvent = "DoubleClick")
    {
        ItemID := TV_GetSelection()
        RetVal := ReturnShortcut(ItemID)
        Msgbox %Retval%
    }   
   
return

ReturnShortcut(ItemID, PathString = "")
{

}

;<doc>
;
; Function: GetItemType
; Description:
;      Returns what type of item is selected in the TreeView.
; Syntax: GetItemType(ItemID)
; Parameters:
;      ItemID - The ItemID of the selected item in the TreeView.
; Return Value:
;      TopParent - The item is the topmost parent in the tree.
;      Parent - The item is a parent item in the treeview, but not the topmost.
;      LowerParent - The item is a parent item but has another parent item above it in the tree.
;      TopChild - The item is the topmost child in a section.
;      Child - The item is a child but not the topmost and it does have a parent.
;      SingleChild - The item is a child but it does not have a parent item in the tree.
; Remarks:
;      This function uses the ItemID to get the parent item, the previous item, and the child item and determine what type of item is selected.
;       See the Return Values section for the different types of items.
; Example:
;      ItemID   := TV_GetSelection()
;      ItemType := GetItemType(ItemID)
;
;</doc>
GetItemType(ItemID)
{
   
   ParentItemID := TV_GetParent(ItemID)
   PrevItemID   := TV_GetPrev(ItemID)
   ChildItemID  := TV_GetChild(ItemID)
   
   If      (ParentItemID  = 0 and ChildItemID != 0 and PrevItemID  = 0)
      return "TopParent"
   else if (ParentItemID  = 0 and ChildItemID != 0 and PrevItemID != 0)
      return "Parent"
   else if (ParentItemID != 0 and ChildItemID != 0 and PrevItemID != 0)
      return "LowerParent"
   else if (ParentItemID != 0 and ChildItemID  = 0 and PrevItemID  = 0)
      return "TopChild"
   else if (ParentItemID != 0 and ChildItemID  = 0 and PrevItemID != 0)
      return "Child"
   else if (ParentItemID  = 0 and ChildItemID  = 0 and PrevItemID != 0)
      return "SingleChild"
      
      
   return 1
   
}


Last edited by entropic on Thu Nov 05, 2009 1:49 am; edited 1 time in total
Back to top
View user's profile Send private message
entropic



Joined: 21 Dec 2008
Posts: 161

PostPosted: Thu Oct 29, 2009 8:00 pm    Post subject: Reply with quote

The code below works but it isn't pretty and it only supports a up to two levels deep. I'm sure someone knows a much better way of doing this...
Code:


Gui, Add, TreeView, R10 gTreeView

P1     := TV_Add("A")
P1C1   := TV_Add("A-1", P1)

P2     := TV_Add("B")
P2C1   := TV_Add("B-1", P2)
P2C2   := TV_Add("B-2", P2)

P3     := TV_Add("C"  , P2)
P3C1   := TV_Add("C-1", P3)
P3C2   := TV_Add("C-2", P3)

P4     := TV_Add("D")
P4C1   := TV_Add("D-1", P4)
P4C2   := TV_Add("D-1", P4)

Gui, Show

return

TreeView:

    If (A_GuiEvent = "DoubleClick")
    {
        ItemID := TV_GetSelection()
        RetVal := ReturnShortcut(ItemID)
        Msgbox %Retval%
    }   
   
return

ReturnShortcut(ItemID, PathString = "")
{
   Prev := TV_GetPrev(ItemID)
   Parent := TV_GetParent(ItemID)
   Next := TV_GetNext(ItemID)
   Child := TV_GetChild(ItemID)
   
   ; If ItemID is a top level item we just walk down the list until we reach it
   CurrentID = 0
   If (Next = 0 and Parent = 0 and Child = 0)
   {
      DownCount = 0
      While (CurrentID != ItemID)
      {
         CurrentID := TV_GetNext(CurrentID)
         If (A_Index != 1)
            DownCount++
      }
      BuildString := "{down " DownCount "}{enter}"
      return BuildString
   }
   
   ; Find the Parent item for the ItemID, if ItemID has more
   ; than one Parent item we loop until we reach the top-most
   ItemsParent := ItemID
   Loop
   {
      
      ItemsParent := TV_GetParent(ItemsParent)
      If (GetItemType(ItemsParent) != "Parent" and GetItemType(ItemsParent) !=  "TopParent")
         LowerParent = True
      else
         break
   }
   
   ; Causes the loop's first iteration to start the search at the top of the tree.
   ; We walk down from the root item to the topmost Parent item for ItemID
   TreeWalkID = 0
   DownCount = 0
   While (TreeWalkID != ItemsParent)
   {
      TreeWalkID := TV_GetNext(TreeWalkID)
      If (A_Index != 1)
          DownCount++    ;BuildString .= "{down}"
   }
   ; We are at the Parent item so we add Enter to the string to open the section
   BuildString := BuildString . "{down " . DownCount . "}{enter}"

   ; Get the Child item for the Parent of ItemID and continue walking   
   TreeWalkID := TV_GetChild(TreeWalkID)
   BuildString .= "{down}"
   DownCount = 0
   If (LowerParent = "True")
   {
      LowerParentID := TV_GetParent(ItemID)
      
      While (TreeWalkID != LowerParentID)
      {
         TreeWalkID := TV_GetNext(TreeWalkID)
         DownCount++
      }
      TreeWalkID := TV_GetChild(TreeWalkID)
      BuildString := BuildString . "{down " . DownCount . "}{enter}{down}"
      
   }
   
   DownCount = 0
   While (TreeWalkID != ItemID)
   {
      TreeWalkID := TV_GetNext(TreeWalkID)
      DownCount++
      
   }
   BuildString := BuildString . "{down " . DownCount . "}{enter}"   
   return BuildString
}

;<doc>
;
; Function: GetItemType
; Description:
;      Returns what type of item is selected in the TreeView.
; Syntax: GetItemType(ItemID)
; Parameters:
;      ItemID - The ItemID of the selected item in the TreeView.
; Return Value:
;      TopParent - The item is the topmost parent in the tree.
;      Parent - The item is a parent item in the treeview, but not the topmost.
;      LowerParent - The item is a parent item but has another parent item above it in the tree.
;      TopChild - The item is the topmost child in a section.
;      Child - The item is a child but not the topmost and it does have a parent.
;      SingleChild - The item is a child but it does not have a parent item in the tree.
; Remarks:
;      This function uses the ItemID to get the parent item, the previous item, and the child item and determine what type of item is selected.
;       See the Return Values section for the different types of items.
; Example:
;      ItemID   := TV_GetSelection()
;      ItemType := GetItemType(ItemID)
;
;</doc>
GetItemType(ItemID)
{
   
   ParentItemID := TV_GetParent(ItemID)
   PrevItemID   := TV_GetPrev(ItemID)
   ChildItemID  := TV_GetChild(ItemID)
   
   If      (ParentItemID  = 0 and ChildItemID != 0 and PrevItemID  = 0)
      return "TopParent"
   else if (ParentItemID  = 0 and ChildItemID != 0 and PrevItemID != 0)
      return "Parent"
   else if (ParentItemID != 0 and ChildItemID != 0 and PrevItemID != 0)
      return "LowerParent"
   else if (ParentItemID != 0 and ChildItemID  = 0 and PrevItemID  = 0)
      return "TopChild"
   else if (ParentItemID != 0 and ChildItemID  = 0 and PrevItemID != 0)
      return "Child"
   else if (ParentItemID  = 0 and ChildItemID  = 0 and PrevItemID != 0)
      return "SingleChild"
       
       
   return 1
   
}
Back to top
View user's profile Send private message
Leef_me



Joined: 08 Apr 2009
Posts: 1158
Location: San Diego, California

PostPosted: Fri Oct 30, 2009 3:50 am    Post subject: Reply with quote

Sorry I didn't get this posted earlier, lost internet connectivity Crying or Very sad
This should support many levels deep. :thumbs-up:

BTW, is that a typo in P4C2 ?
Code:
Gui, Add, TreeView, R10 gTreeView

P1     := TV_Add("A")
P1C1   := TV_Add("A-1", P1)

P2     := TV_Add("B")
P2C1   := TV_Add("B-1", P2)
P2C2   := TV_Add("B-2", P2)

P3     := TV_Add("C"  , P2)
P3C1   := TV_Add("C-1", P3)
P3C2   := TV_Add("C-2", P3)

P4     := TV_Add("D")
P4C1   := TV_Add("D-1", P4)
P4C2   := TV_Add("D-1", P4)

Gui, Show

return

TreeView:

    If (A_GuiEvent = "DoubleClick")
    {
        ItemID := TV_GetSelection()
;   msgbox %ItemID%
        RetVal := ReturnShortcut(ItemID)
        Msgbox %Retval%
    }   
   
return

ReturnShortcut(ItemID, PathString = "")
{
  tempid:=ItemID

  loop
  {
    b_index:=a_index   ; this a_index is needed through all loops

    prevcnt%b_index%=0
    Parentcnt%b_index%=0
    loop
    {
       Prev := TV_GetPrev(tempid)
       prevcnt%b_index%++
       if prev = 0
          break
;       prevcnt%b_index%++
       tempid:=Prev
    }
    Parent := TV_GetParent(tempid)
    if Parent = 0
       break
    Parentcnt%b_index%++
    tempid:=Parent
  }
  c_index:=b_index
;listvars

; becuase the top of the list starts on a parent, we must subtract one sibling count
       prevcnt%b_index%--

/*
; early diagnostic
loop, %c_index%
{
;msgbox % "!" Parentcnt%a_index% "!" prevcnt%a_index% "!"
}

*/

    BuildString :=""

  while c_index
  {
     f:=Parentcnt%c_index%
     e:=prevcnt%c_index%
     if %f%
       BuildString .= "{Right=" f "}"
     if %e%
       BuildString .=  "{Down=" e "}"

    c_index--
  }
;listvars
;msgbox full %b_index%!%BuildString%
  return BuildString
}
Back to top
View user's profile Send private message
entropic



Joined: 21 Dec 2008
Posts: 161

PostPosted: Thu Nov 05, 2009 1:49 am    Post subject: Reply with quote

Leef_me you are amazing, sorry for the delay in my reply, I went on a trip.
Yeah, that is a typo on P4C2.

Thank you very much for your help!
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Ask for Help All times are GMT
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group