Announcement

Collapse
No announcement yet.

Treeview Reselect Problem

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    #21
    Here's another example - going the long way round.
    Code:
        CASE %WM_NOTIFY
          lpNmh = CBLPARAM
          SELECT CASE @lpNmh.idFrom
            CASE %TRV_SYSTREEVIEW32_1
              hTreeView = @lpNmh.hwndFrom                             ' <* TreeView handle
     
              IF @lpNmh.Code = %NM_CLICK  THEN
                LOCAL ht AS TV_HITTESTINFO
                LOCAL dwpos AS DWORD
                LOCAL iTmp AS INTEGER
                dwpos = GetMessagePos()                               ' Cursor Pos at time of click in screen coords
                iTmp = LO(WORD, dwpos)                                ' "MAKEPOINT" better for multiple monitors?
                ht.pt.x = iTmp
                iTmp = HI(WORD, dwpos)
                ht.pt.y = iTmp
                MapWindowPoints(%HWND_DESKTOP, hTreeView, ht.pt, 1)   ' Map to position in ListView control
                CALL TreeView_HitTest(hTreeView, ht)                  ' test that position, on item text?
                IF ht.flags = %TVHT_ONITEMLABEL THEN
                  hTreeItem = ht.hItem
                END IF
                 TreeView_SelectItem hTreeView, 0                     ' stimulate %TVN_SELCHANGED msg
              END IF                                                  ' (if rqd - for second click of selected item)
     
              IF @lpNmh.code = %TVN_SELCHANGED THEN
                LOCAL lpTV AS NM_TREEVIEW PTR
                lpTV = CBLPARAM
                SELECT CASE @lpTV.action                              ' what action caused selection change?
                  CASE %TVC_BYMOUSE
                    DIALOG SET TEXT CBHNDL, TVGetText(hTreeView, hTreeItem) +" By Click "+ TIME$
                  CASE %TVC_BYKEYBOARD
                    hTreeItem = Treeview_GetSelection(hTreeView)
                    DIALOG SET TEXT CBHNDL, TVGetText(hTreeView, hTreeItem) +" By Key "+ TIME$
                  CASE ELSE
                    DIALOG SET TEXT CBHNDL, TVGetText(hTreeView, hTreeItem) +" Unknown "+ TIME$
                END SELECT
              END IF
          END SELECT
    Rgds, Dave

    Comment


      #22
      Originally posted by Dave Biggs View Post
      In Post #5 Gosta pointed out that "TVGetText is not returning anything. I thought it would return the Item name (Root#, Item#, or SubItem#)".
      I though that's what the code was doing too - 'til i tried it myself
      It seems that hTreeItem& is not being set in the original code.
      Good job, Dave. I was beginning to think I would never get it. Thanks. I've been playing around with it (even added a 4th dimension). Still would like to get an Id number for each cell so I could work with an array of Ids, but haven't figured that out yet. (What has helped me is removing/replacing the standard PBForms Ids with more Dummy understandable names.)

      '
      Code:
      'http://www.powerbasic.com/support/pbforums/showthread.php?t=39348
      #Compile Exe
      #Dim All
      '------------------------------------------------------------------------------
      '   ** Includes **
      '------------------------------------------------------------------------------
      #If Not %Def(%WINAPI)
        #Include "WIN32API.INC"
      #EndIf
      #If Not %Def(%COMMCTRL_INC)
        #Include "COMMCTRL.INC"
      #EndIf
      '------------------------------------------------------------------------------
       
      '------------------------------------------------------------------------------
      '   ** Constants **
      '------------------------------------------------------------------------------
      %Tree_View_Handle = 1001
      %Send_Sel_Btn = 1002
      %Results_Tb = 1003
      '------------------------------------------------------------------------------
      Global Tree_Ids() As Long 'Not used (yet)
      '
      Function TVGetText(ByVal hTree As Long, ByVal hTVItem As Long, Tv_Item_Number As Long) As String
          Local zText As Asciiz * 255
          Local lTVItem As TV_ITEM
      '
          lTVItem.hItem = hTVItem
          lTVItem.Mask = %TVIF_TEXT
          lTVItem.pszText = VarPtr(zText)
          lTVItem.cchTextMax = 255
          TreeView_GetItem(hTree, lTVItem)   
          '
          Tv_Item_Number = lTVItem.hItem
      '
          Function = zText
      End Function 
      '
      Function PBMain()
        ShowDIALOG1 %HWND_DESKTOP
      End Function
      '------------------------------------------------------------------------------
      '
      '------------------------------------------------------------------------------
      '   ** CallBacks **
      '------------------------------------------------------------------------------
      CallBack Function ShowDIALOG1Proc()
      '
      Static CellNum, hTreeItem, hTreeView As Long
      Static LpNmh_Code, Cell_Name As String
      '
      Dim lpNmh As NMHDR Ptr    
      '
      Local nh As NmHdr 
      Local Item_Num As Long
      Local u As String
      '
        u$ = " \       \   \                  \    \            \    #####"
      '
        Select Case As Long CbMsg
          Case %WM_INITDIALOG
            ' Initialization handler      
       
          Case %WM_NOTIFY
            Local Cell_Num As Dword
            Select Case CbCtl
              Case %Tree_View_Handle
                Control Handle CbHndl, %Tree_View_Handle To hTreeView&
                lpNmh = CB.lParam  
                  'all these return zero
      '           Cell_Num = TreeView_GetSelection(CB.Hndl)
      '           Cell_Num = NH.hwndFrom
      '           Cell_Num = NH.IdFrom
                 '
                Select Case @lpNmh.Code                 
                  Reset LpNmh_Code$ 'Reset for display purposes, else Dialog Title keeps updating time below
                  Case %TVN_SELCHANGED
                    LpNmh_Code = "%TVN_SELCHANGED"
                    hTreeItem = Treeview_GetSelection(hTreeView)
                    Cell_Name$ = TVGetText(hTreeView, hTreeItem, Item_Num)
                    Cell_Num = Item_Num      '<<  Always zero?
                  '             
                  Case %Nm_Return 'Never hit - maybe need Style in setting up?
                    LpNmh_Code = "%Nm_Return"
                  '
                  Case %NM_Dblclk
                    LpNmh_Code = "%NM_Dblclk"
                     Dialog Set Text CbHndl, Time$ & " %Nm_DblClk" & Str$(Cell_Num)
                  Case %NM_LDOWN
                    LpNmh_Code = "%NM_LDOWN"
                  '
                  Case %NM_CLICK 
                    LpNmh_Code = "%NM_CLICK"
                  '   
                  Case %TVN_KEYDOWN
                    LpNmh_Code = "%TVN_KEYDOWN"
                End Select              
                '
                If LpNmh_Code$ > "" Then 'key above pressed
                   Dialog Set Text CbHndl,  Using$(u$, Time$, LpNmh_Code$, Cell_Name$, Cell_Num)
                End If
            End Select
          Case %WM_COMMAND
            ' Process control notifications
              Select Case CbCtl  
                 Case %Send_Sel_Btn  'Update textbox on button click
                    If CbCtlMsg = %BN_CLICKED Or CbCtlMsg = 1 Then
                       Control Set Text CbHndl, %Results_Tb, Cell_Name$
                    End If
                 Case %Tree_View_Handle 
                 ? Str$(CbCtl),, "at %Tree_View_Handle" '<< never gets hit
            End Select
        End Select
      End Function
      '------------------------------------------------------------------------------
      '------------------------------------------------------------------------------
      '   ** Sample Code **
      '------------------------------------------------------------------------------
      Function SampleTreeViewInsertItem(ByVal hTree As Dword, ByVal hParent As Dword, sItem As String) As Long
        Local tTVItem   As TV_ITEM
        Local tTVInsert As TV_INSERTSTRUCT
        If hParent Then
          tTVItem.mask      = %TVIF_CHILDREN Or %TVIF_HANDLE
          tTVItem.hItem     = hParent
          tTVItem.cchildren = 1
          TreeView_SetItem hTree, tTVItem
        End If
        tTVInsert.hParent              = hParent
        tTVInsert.Item.Item.mask       = %TVIF_TEXT
        tTVInsert.Item.Item.pszText    = StrPtr(sItem)
        tTVInsert.Item.Item.cchTextMax = Len(sItem)
        Function = TreeView_InsertItem(hTree, tTVInsert)
      End Function
      '------------------------------------------------------------------------------
      '------------------------------------------------------------------------------
      Function SampleTreeView(ByVal hDlg As Dword, ByVal lID As Long, ByVal lCount As Long) As Long
        Local i, j, k, l       As Long
        Local hCtl, hRoot, hParent, hChile As Dword
        Control Handle hDlg, lID To hCtl
        For i = 1 To lCount
          hRoot = SampleTreeViewInsertItem(hCtl, %Null, Using$("Animal #", i))
          For j = 1 To lCount
            hParent = SampleTreeViewInsertItem(hCtl, hRoot, Using$("Species #", j))
            For k = 1 To lCount
      '        hChile = SampleTreeViewInsertItem(hCtl, hParent, Using$("Item #", j))
              hChile = SampleTreeViewInsertItem(hCtl, hParent, Using$("Dog # ", k))
              For l = 1 To lCount
                Call SampleTreeViewInsertItem(hCtl, hChile, Using$("Breed # ", l))
              Next l
            Next k
          Next j
        Next i
      End Function
      '------------------------------------------------------------------------------
      '------------------------------------------------------------------------------
      '   ** Dialogs **
      '------------------------------------------------------------------------------
      Function ShowDIALOG1(ByVal hParent As Dword) As Long
        Local Row, Col, Hgt, Wd, lRslt As Long           
        Local hDlg  As Dword
         Row = 69
         Col = 90
         Wd = 399
         Hgt = 304
      '
        Dialog New hParent, "Dialog1", Col, Row, Wd, hgt, %WS_POPUP Or %WS_BORDER Or _
          %WS_DLGFRAME Or %WS_SYSMENU Or %WS_CLIPSIBLINGS Or %WS_VISIBLE Or _
          %DS_MODALFRAME Or %DS_3DLOOK Or %DS_NOFAILCREATE Or %DS_SETFONT, _
          %WS_EX_CONTROLPARENT Or %WS_EX_LEFT Or %WS_EX_LTRREADING Or _
          %WS_EX_RIGHTSCROLLBAR, To hDlg
      '
        Control Add "SysTreeView32", hDlg, %Tree_View_Handle, "SysTreeView32_1", _
          44, 28, 252, 184, %WS_CHILD Or %WS_VISIBLE Or %WS_TABSTOP Or _
          %TVS_HASBUTTONS Or %TVS_HASLINES Or %TVS_LINESATROOT Or _
          %TVS_SHOWSELALWAYS, %WS_EX_LEFT Or %WS_EX_CLIENTEDGE Or _
          %WS_EX_RIGHTSCROLLBAR
      '
        SampleTreeView hDlg, %Tree_View_Handle, 3 'create the Treeview
      '
          Control Add TextBox, hDlg, %Results_Tb,   "Selected",       Col + 10, Hgt - 50, 70, 15
           Control Add Button, hDlg, %Send_Sel_Btn, "Send selection", Col + 10, Hgt - 25, 70, 15
      '
        Dialog Show Modal hDlg, Call ShowDIALOG1Proc To lRslt
      '
      End Function
      '------------------------------------------------------------------------------
      '
      ====================================================
      "Anything that is too stupid to be spoken is sung."
      Voltaire (1694-1778)
      ====================================================
      Last edited by Gösta H. Lovgren-2; 14 Dec 2008, 10:29 AM.
      It's a pretty day. I hope you enjoy it.

      Gösta

      JWAM: (Quit Smoking): http://www.SwedesDock.com/smoking
      LDN - A Miracle Drug: http://www.SwedesDock.com/LDN/

      Comment


        #23
        Still would like to get an Id number for each cell so I could work with an array of Ids, but haven't figured that out yet.
        An array of hitems? Or, an actual user-assigned "node id #?"

        For the former, you have to walk the tree recursively. I am pretty sure there is code here to do this, but if not I can gin some up for you.

        For the latter, you can use the "lparam" member of the TVITEM structure, which you can set when you add the item (not sure if doable with DDT syntax) or later with Treeview_SetItem. Just make sure your TVITEM.mask member contains the TVIF_PARAM bit.

        MCM
        Michael Mattias
        Tal Systems (retired)
        Port Washington WI USA
        [email protected]
        http://www.talsystems.com

        Comment


          #24
          Here it is..
          Code:
          DECLARE FUNCTION TV_Enum_User_Callback _
             (BYVAL dwUserData AS LONG, tvi AS TV_ITEM, BYVAL hTV AS LONG) AS LONG
          ' Return TRUE to continue enumeration or FALSE to terminate
          ' dwuser data is what is passed as parameter four (dwUser).
          
          
          ' required TSI library file AVAILABLE IN SOURCE CODE FORUM search 'malloc' 
          #IF NOT %DEF(%MALLOC_INC)
            #INCLUDE "malloc.inc"
          #ENDIF
          
          ' === ENUMERATE THE NODES OF A TREE STARTING WITH THE hItem of the 'root' of the tree.
          ' =====================================================================================
          ' actual recursing function; returns 0 = Enum Completed, 1 = Enum was terminated in callback
          ' This function enumerates the tree whose root is hStartItem. Includes hStartItem
          ' ***************************************************************************
          ' THIS FUNCTION SHOULD NOT BE CALLED BY THE USER, CALL TV_ENUMTREE or TV_ENUMTREE_SIBLINGS Instead
          ' ***************************************************************************
          FUNCTION Treeview_Enum_Recursing_Function (hTV AS LONG, hStartItem AS LONG, BYVAL CbAddress AS DWORD, _
                    BYVAL dwUserData AS LONG, BYVAL doSiblings AS LONG, BYVAL ResetStop AS LONG ) AS LONG
          
              LOCAL hItem AS LONG, hChild AS LONG, hSibling AS LONG, tvi AS TV_ITEM
              LOCAL DoSibs AS LONG
              LOCAL szText AS ASCIIZ * %TV_ENUM_MAX_TEXT_LEN
          
              LOCAL  Continue AS LONG
              STATIC StopEnum AS LONG   ' yes, STATIC, so we can exit multiple levels of recursion
          
              IF ResetStop THEN         ' reset stop is set on each "fresh" enumeration
                StopEnum = %FALSE
              END IF
              IF StopEnum THEN    ' user forced a stop in callback (recursions are called with resetStop=false)
                 FUNCTION = 1
                 EXIT FUNCTION
              END IF
              ' get stuff into LOCAL vars to make sure each recursion gets own copy
              hItem      = hStartItem
              DoSibs     = DoSiblings  ' for first time, will be false, so will not do siblings; when
                                       ' called from restart, doSibs WILL be true!
              DO WHILE hItem
                ' get the tvi for this item and send it to the callback function
                tvi.hItem       = hItem    ' we want this one
                tvi.mask        = %TV_ENUM_MASK
                tvi.cchTextMax  = SIZEOF(szText)
                tvi.pszText     = VARPTR(szText)
                TreeView_GetItem hTv, BYVAL VARPTR(tvi)
                ' send tvi to the USER callback function
                CALL DWORD cbAddress _
                  USING TV_Enum_User_callback  _
                     (dwUserData, tvi, htv) TO Continue
                    ' TRACE PRINT "Callback returns continue=" & STR$(Continue)
                     IF ISFALSE Continue THEN
                         StopEnum          = %TRUE     ' set the static stop flag which will be read
                                                       ' as function recurses out of itself.
                         EXIT DO
                     END IF
                ' if any children of this node, call this function recursively.
                hChild = TreeView_GetChild(hTV,hItem)
                IF hChild THEN
                    ' The GetChild macro returns the first child of hItem in hTv
                    ' call ourself, but now the child is the starting item and we do siblings and do NOT reset the Stop flag
                     CALL Treeview_Enum_Recursing_Function (hTv, hChild, CbAddress, dwUserData, %TRUE, %FALSE)
                END IF
                IF StopEnum THEN
                    EXIT DO
                END IF
          
                ' and make hitem the next sibling at this level, if doing siblings
                IF DoSibs THEN
                    hItem = TreeView_GetNextSibling (hTv, hItem)
                ELSE
                    hItem = %NULL
                END IF
              LOOP
              ' if we get here, enum completed without user action
              FUNCTION = 0
          
          END FUNCTION
          
          ' ===============================================================================
          '                USER-CALLED TREE ENUMERATION FUNCTIONS
          ' Treeview_enumtree: Enumerate the nodes of the tree whose root is at hStartItem
          '                NOTE: does NOT do siblings of hStartItem!
          
          '================================================================================
          FUNCTION TreeView_EnumTree (hTV AS LONG, hStartItem AS LONG, BYVAL CbAddress AS DWORD, BYVAL dwUserData AS LONG) AS LONG
            ' here we just start the recursion, FALSE, TRUE ==> NO siblings, YES reset stop flag
             LOCAL I AS LONG
             CALL TreeView_Enum_Recursing_Function _
                  (hTv, hStartItem, CbAddress, dwUserData, %TV_ENUM_SIBLINGS_NO, %TRUE) TO I
             FUNCTION = I
          END FUNCTION
          Just set hStartItem = root of tree and call Treeview_enumTree.

          For your user-data... well handling an array can be tricky. You have to allocate enough space for the data : treeview_getCount() * sizeof(data for each node of tree)

          Pass a pointer BY REFERENCE ( not directly supported by compiler) to the callback, starting with element zero of your array, and each time you enter your callback procedure increment its target by the size of the data.

          Or, use GLOBAL variables. (Which in this case is much easier to understand).

          MCM
          Michael Mattias
          Tal Systems (retired)
          Port Washington WI USA
          [email protected]
          http://www.talsystems.com

          Comment


            #25
            Thanks, M. I'll look into that.

            =================================
            "He would make a lovely corpse."
            Charles Dickens (1812-1870)
            =================================
            It's a pretty day. I hope you enjoy it.

            Gösta

            JWAM: (Quit Smoking): http://www.SwedesDock.com/smoking
            LDN - A Miracle Drug: http://www.SwedesDock.com/LDN/

            Comment


              #26
              Thanks David for the long way around code. I need to consider that also.



              Good points, all.

              Bob Mechler

              Comment

              Working...
              X
              😀
              🥰
              🤢
              😎
              😡
              👍
              👎