Programmers? Looking for help with a treeview function

Started by scooter, October 11, 2015, 01:44:55 PM

Previous topic - Next topic

scooter

Hi everyone.  Looking for some help with a small problem.  For years, Iââ,¬â,,¢ve been using the treeview and listview functions originally created by Guido back in the early 2000ââ,¬â,,¢s.  In the code below, I build a treeview and populate it 7 levels deep.  I then select the last object in order to expand the tree.  It expands the structure but it does not select, and highlight the last item.

Iââ,¬â,,¢m an ace with Winbatch, but when it comes to programming code, binary, dll calls, etc, my knowledge is very limited.  Any help would be greatly appreciated!

Thanks

Scott



;-------------------------------------------------------------
;The following functions were part of the treeview and listview
;controls quido created several years ago
;-------------------------------------------------------------

;TVCreate()   : Creates a treeview control
;x            : pixels from left
;y            : pixels from top                                                       
;w            : width in pixels                                                       
;h            : height in pixels                   
;style      : TV style, see API constants
;handle      : dialog handle returned by the dialog procedure
;Returns   : treeview handle if succesful , 0 otherwise
#definefunction TVCreate(x, y, w, h, style, handle)
   user32   =   strcat(dirwindows(1), "user32.dll")
   WS_CHILD               = 1073741824
   WS_VISIBLE             = 268435456
   WS_TABSTOP            =   65536
   WS_EX_CLIENTEDGE   =   512
   hinst   =   dllhinst("")
   return dllcall(user32, long:"CreateWindowExA", long:WS_EX_CLIENTEDGE, lpstr:"SysTreeView32", lpstr:"", long:WS_CHILD|WS_VISIBLE|WS_TABSTOP|style, long:x, long:y, long:w, long:h, long:handle, long:0, long:hinst, long:0)
#endfunction

;TVInsertItem()   : Inserts an item in a treeview control
;htree            :    treeview handle returned by TreeCreate()                         
;insertafter   :    item handle after wich the new item will be inserted , or:       
;                           TVI_FIRST   :   Inserts the item at the beginning of the list         
;                           TVI_LAST   :   Inserts the item at the end of the list               
;                           TVI_ROOT   :   Add the item as a root item                           
;                           TVI_SORT   :   Inserts the item into the list in alphabetical order
;text                  : item text                                                         
;hparent            : handle of parent item , if this member is the TVI_ROOT value or 0
;                           the item is inserted at the root of the tree-view control   
;iImage               : Index(0 based) in the tree-view control's image list of the icon image to use when the item is in the nonselected state
;                           If you are not using images put a negative value for this parameter.
;iSelectedImage   : Index(0 based) in the tree-view control's image list of the icon image to use when the item is in the selected state   
;Returns         : handle to the new item if successful, or 0 otherwise             
#definefunction TVInsertItem(htree, insertafter, text, hparent, iImage, iSelectedImage)
   user32   =   strcat(dirwindows(1), "user32.dll")
   TV_FIRST            =   4352
   TVIF_TEXT            =   1
   TVM_INSERTITEM   =   TV_FIRST+0
   TVIF_IMAGE         =   2
   TVIF_SELECTEDIMAGE = 32
   
   TVINSERTSTRUCT   =   binaryalloc(48)
   binarypoke4(TVINSERTSTRUCT, 0, hparent)    ;hParent
   binarypoke4(TVINSERTSTRUCT, 4, insertafter);hInsertAfter
   
   ;TVITEM
   mask = TVIF_TEXT
   if iImage>=0
      mask = mask | TVIF_IMAGE | TVIF_SELECTEDIMAGE
      binarypoke4(TVINSERTSTRUCT, 32, iImage)
      binarypoke4(TVINSERTSTRUCT, 36, iSelectedImage)
   endif
      
   binarypoke4(TVINSERTSTRUCT, 8, mask)   ;mask
   textlen   =   strlen(text)
   textbuf   =   binaryalloc(textlen+1)
   binarypokestr(textbuf, 0, text)
   binarypoke4(TVINSERTSTRUCT, 24, intcontrol(42, textbuf, 0, 0, 0)) ;pszText
   
   ret   =   dllcall(user32, long:"SendMessageA", long:htree, long:TVM_INSERTITEM, long:0, lpbinary:TVINSERTSTRUCT)
   binaryfree(textbuf)
   binaryfree(TVINSERTSTRUCT)
   return ret
#endfunction


;TVGetSelected()   :   Returns handle of selected item or 0 if no item selected
;htree : treeview handle
#definefunction TVGetSelected(htree)
   user32   =   strcat(dirwindows(1), "user32.dll")
   TVGN_CARET         =   9
   TVM_GETNEXTITEM   =   4352 + 10
   return dllcall(user32, long:"SendMessageA", long:htree, long:TVM_GETNEXTITEM, long:TVGN_CARET, long:0)
#endfunction


;-------------------------------------------------------------
;I muddled around and managed to add this function a few years ago
;-------------------------------------------------------------
#definefunction TVMSELECTITEM(htree,item)
   user32  = strcat(dirwindows(1), "user32.dll")
   TVM_SELECTITEM=4363
   TVGN_FIRSTVISIBLE=5
   TVGN_CARET = 9
   return dllcall(user32, long:"SendMessageA", long:htree, long:TVM_SELECTITEM, long:TVGN_FIRSTVISIBLE, long:item)
#endfunction






;-------------------------------------------------------------
;Here is the test dialog.  It builds a tree structure 7 levels deep,
;and expands the branch.  However, it does not highlight the selected item
;-------------------------------------------------------------
#DEFINESUBROUTINE DEFAULT(MYDIALOG, EVENTCODE, CONTROL, RES4, RES5)
SWITCH(EVENTCODE)
CASE 0
   DIALOGPROCOPTIONS(MYDIALOG, 2,1) ;PUSH BUTTON

   ;CREATE THE TREEVIEW
   TVS_LINES = 2 
   TVS_PLUSSIGNS = 1
   TREEVIEW = TVCREATE(14,14,540,390,TVS_LINES|TVS_PLUSSIGNS,MYDIALOG)

   ;ADD A 7 ITEM BRANCH
   POSITION = 0
   FOR A = 1 TO 7
      TVI_LAST = -65534
      POSITION = TVINSERTITEM(TREEVIEW,TVI_LAST,A,POSITION,0,0)
   NEXT

   ;SELECT THE 7TH ITEM TO EXPAND THE BRANCH
   TVMSELECTITEM(TREEVIEW,POSITION)
   RETURN -2
BREAK

CASE 2
   IF CONTROL == "PB_GET" THEN
      ;GET THE SELECTED ITEM FROM THE TREEVIEW
      SELECTED = TVGETSELECTED(TREEVIEW)
      MESSAGE("Selected item...",SELECTED)
      RETURN -2
   END IF
BREAK
END SWITCH
#ENDSUBROUTINE

MyDialogFormat=`WWWDLGED,6.2`

MyDialogCaption=`Until you manually highlight an item, the "Get Selection" button only returns 0`
MyDialogX=5000
MyDialogY=5000
MyDialogWidth=288
MyDialogHeight=235
MyDialogNumControls=002
MyDialogProcedure=`DEFAULT`
MyDialogFont=`DEFAULT`
MyDialogTextColor=`DEFAULT`
MyDialogBackground=`DEFAULT,DEFAULT`
MyDialogConfig=0

MyDialog001=`087,205,044,012,PUSHBUTTON,"PB_GET",DEFAULT,"Get Selection",1,1,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
MyDialog002=`141,205,044,012,PUSHBUTTON,"PB_CANCEL",DEFAULT,"Close",0,2,DEFAULT,DEFAULT,DEFAULT,DEFAULT`

ButtonPushed=Dialog("MyDialog")





JTaylor

Not sure I am understanding...when I run the script it opens with the treeview expanded.  That is, it shows the stairsteps from 1 to 7 with none of the items having any branches themselves.  I can select any of them, including 7, and get a response.  This sounds different from what you describe though.   

Jim

scooter

Hey Jim.  Thanks for the reply.

Right now... if you press the "Get Selection" button immediately after load, it will return zero.  Once you manually highlight one of the items, it will then return the selected item's value.

What I want to happen is... The last item (7) in the branch to be highlighted.  So when you press the "get selection" button immediately after load, it returns the item value for #7.  Without the need to manually highlight it first.

Hope that helps,

Scott

....IFICantBYTE

Hi Scott,
haven't seen you around for a long time..

Anyway, it looks like you need to change the wParam in your TVMSELECTITEM function so that it uses TVGN_CARET rather than TVGN_FIRSTVISIBLE.
Basically, the last item is not actually being selected, it is just made sure that it is visible (in case there are too many to fit in the window) when called with the TVGN_FIRSTVISIBLE parameter value.
The TVGN_CARET is the one that actually selects the specified item handle.

Try replacing your TVMSELECTITEM UDF with this amended version and see how you go:
Code (winbatch) Select
#definefunction TVMSELECTITEM(htree,item)
   user32  = strcat(dirwindows(1), "user32.dll")
   TVM_SELECTITEM=4363;TVFIRST + 11
   ;wParam can be ONE of the following values:
   TVGN_CARET = 9;Sets the selection to the specified item. The tree-view control's parent window receives the TVN_SELCHANGING and TVN_SELCHANGED notification codes.
   TVGN_DROPHILITE = 8;Redraws the specified item in the style used to indicate the target of a drag-and-drop operation.
   TVGN_FIRSTVISIBLE = 5;Ensures that the specified item is visible, and, if possible, displays it at the top of the control's window. Tree-view controls display as many items as will fit in the window. If the specified item is near the bottom of the control's hierarchy of items, it might not become the first visible item, depending on how many items fit in the window.
   ;TVSI_NOSINGLEEXPAND = 32768; Can't use this easily in WinBatch: To use this flag, you must provide a manifest specifying Comclt32.dll version 6.0.
   return dllcall(user32, long:"SendMessageA", long:htree, long:TVM_SELECTITEM, long:TVGN_CARET, long:item)
#endfunction
Regards,
....IFICantBYTE

Nothing sucks more than that moment during an argument when you realize you're wrong. :)

scooter

Yeah, haven't posted anything in a long time.  Still use Winbatch all the time though.  Greatest tool around! ;-)

Yay!  That solved my problem.

Thanks so much!!

Scott


....IFICantBYTE

Regards,
....IFICantBYTE

Nothing sucks more than that moment during an argument when you realize you're wrong. :)