Announcement

Collapse
No announcement yet.

Treeview question

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

  • Michael Mattias
    replied
    You know, you don't have to handle the keys yourself with the standard treeview control; the left, right, up and down arrows all do expand/collapse navigate.

    As far as "select (or simply 'highlight') the first child of the selected item (via click or keyboard)", that you *do* have to do yourself, as the default behavior is to select the node clicked or to which you have navigated.

    I learned all this when I had to replace a standard treeview control with "something else"; I spent a lot of time playing with the standard treeview so I could emulate its behavior. Yes, I *was* surprised by all the stuff it does with the arrow keys.

    MCM

    Leave a comment:


  • BOB MECHLER
    replied
    Working example

    So far this is the best I can come up with starting with Tonny's code. I've changed a place or two where Michael rightly questioned the use of CBCTL in WM_NOTIFY.

    The program is supposed to react to a click on the parent node by expanding the child nodes and highlighting the first one. Using the down arrow and coming up on another parent node will auto expand that node. Please do that will several nodes. Once several are open, use the up and down arrows and it should jump over the Parent nodes.

    The mouse works to collapse or expand any parent node that doesn't have a highlighted item in it.

    The left arrow will collapse every node it's on when pressed and the same is true of the right arrow.

    The action I'm looking for is similar to a panel control where the sub items sit directly beneath the section headers which look like buttons that float up and down based on expanding or collapsing. This method however allows many nodes to be open at the same time with a scroll bar.


    Please see notes in comment section and especially the code in TVN_SELCHANGED area.

    Bob Mechler
    Code:
    'MESSAGE http://www.powerbasic.com/support/forums/Forum7/HTML/003114.html
    'FORUM:  Source Code
    'TOPIC:  Basic TreeView LPStr_TextCallBack Demo
    'NAME:   Tonny Bjorn, Member
    'DATE:   March 05, 2007 09:51 AM
    
    
    '==============================================================================
    ' Basic demo on using large amounts of data into TreeView using %LPSTR_TEXTCALLBACK
    ' and %TVN_GETDISPINFO for better performance. NB: %LVN_GETDISPINFO for ListView
    '------------------------------------------------------------------------------
    ' Used Compiler: PB/WIN 8.03
    ' WIN32API Date: 01*Feb*2005 (Updated 27 January 2005)
    ' COMMCTRL Date: 01*Feb*2005 (Updated 27 October 2003)
    ' Prg tested on: Windows 2000 SP3, Windows XP Pro SP2
    ' 03/11/09 by Bob Mechler
    'changed slightly to test skipping level one nodes and opening up access to
    ' the child nodes as in a Menu where section headers divide up the menu into
    ' logical divisions and serve as a place to expand or collapse a long menu
    ' in other words the Parent node level should only expand or collapse the next
    ' level
    ' Looking for any comments
    '==============================================================================
    #COMPILE EXE 
    #DIM ALL
    
    %USEMACROS = 1
    
    #INCLUDE "WIN32API.INC"
    #INCLUDE "COMMCTRL.INC"
    
    '==============================================================================
    %ID_TREEVIEW            = 100
    
    '==============================================================================
    GLOBAL hTreeView        AS LONG     ' TreeView Handle
    GLOBAL TVTextArray()    AS STRING   ' TreeView Text Label Storage
    
    '==============================================================================
    ' Get the text from the selected item in the TreeView
    '------------------------------------------------------------------------------
    ' hTree     - TreeView Handle
    ' hTVItem   - Selected TreeView item
    '==============================================================================
    FUNCTION TVGetText(BYVAL hTree AS LONG, BYVAL hTVItem 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)
        FUNCTION = zText
    END FUNCTION
    
    '==============================================================================
    ' Insert an item in the TreeView using LPSTR_TEXTCALLBACK for improved speed
    '------------------------------------------------------------------------------
    ' hTree     - TreeView handle
    ' hParent   - Handle for position type (root, parent child) in the tree
    ' lItemNum  - Indicator coresponding to the text in the TVTextArray for the TreeView
    ' lTextMax  - Length of the string being added
    '==============================================================================
    FUNCTION TVInsertLPSTRItem(BYVAL hTree AS LONG, BYVAL hParent AS LONG, BYVAL lItemNum AS LONG, BYVAL lTextMax AS LONG) AS LONG
        LOCAL tTVInsert   AS TV_INSERTSTRUCT
        LOCAL tTVItem     AS TV_ITEM
        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 OR %TVIF_PARAM
        tTVInsert.Item.Item.pszText = %LPSTR_TEXTCALLBACK
        tTVInsert.Item.Item.cchTextMax = lTextMax
        tTVInsert.Item.Item.lParam  = lItemNum
        FUNCTION = TreeView_InsertItem(hTree, tTVInsert)
    END FUNCTION
    
    '==============================================================================
    FUNCTION FillTreeViewTest(BYVAL lCount AS LONG) AS LONG
        LOCAL hTopRoot  AS DWORD
        LOCAL hRoot     AS DWORD
        LOCAL hParent   AS DWORD
        LOCAL hChild    AS DWORD
        LOCAL g         AS LONG
        LOCAL h         AS LONG
        LOCAL i         AS LONG
        LOCAL j         AS LONG
        LOCAL k         AS LONG
        LOCAL sBuffer   AS STRING
    
        k = 0
    
        ' =======================================================================
        ' Test if array is big enough to hold string, else REDIM and add a
        ' little extra to minimize slow redim process time. The extra array
        ' overhead is balanced out by improved speed.
        IF UBOUND(TVTextArray) < k THEN REDIM PRESERVE TVTextArray(k + 100)
    
        ' Add string to array for %LPSTR_TEXTCALLBACK
        'TVTextArray(k) = "Root"
    
        ' Insert the item in the TreeView
        'hTopRoot = TVInsertLPSTRItem(hTreeView, 0, k, LEN(TVTextArray(k)))
        hTopRoot = 0
        ' =======================================================================
    
        FOR i = 1 TO lCount
    
            ' Add Parent
            sBuffer = "Parent Pos #" & FORMAT$(i)
    
            INCR k
    
            IF UBOUND(TVTextArray) < k THEN REDIM PRESERVE TVTextArray(k + 100)
    
            TVTextArray(k) = sBuffer
    
            hRoot = TVInsertLPSTRItem(hTreeView, hTopRoot, k, LEN(TVTextArray(k)))
    
            ' Add Childs
            FOR j = 1 TO 5
    
                INCR k
    
                IF UBOUND(TVTextArray) < k THEN REDIM PRESERVE TVTextArray(k + 100)
    
                TVTextArray(k) = "Child1 Pos #" & FORMAT$(j)
    
                hParent = TVInsertLPSTRItem(hTreeView, hRoot, k, LEN(TVTextArray(k)))
    
                ' Add Childs
                FOR h = 1 TO 5
    
                    INCR k
    
                    IF UBOUND(TVTextArray) < k THEN REDIM PRESERVE TVTextArray(k + 100)
    
                    TVTextArray(k) = "Child2 Pos #" & FORMAT$(h)
    
                    hChild = TVInsertLPSTRItem(hTreeView, hParent, k, LEN(TVTextArray(k)))
    
                    ' Add Subs
                    FOR g = 1 TO 3
    
                        INCR k
    
                        IF UBOUND(TVTextArray) < k THEN REDIM PRESERVE TVTextArray(k + 100)
                        TVTextArray(k) = "Sub Pos #" & FORMAT$(g)
                        TVInsertLPSTRItem(hTreeView, hChild, k, LEN(TVTextArray(k)))
    
                    NEXT
    
                NEXT
    
            NEXT
    
        NEXT
    
        FUNCTION = k
    
        DIALOG DOEVENTS
    
    END FUNCTION
    
    '==============================================================================
    CALLBACK FUNCTION DialogProc()
        LOCAL lpTV          AS NM_TREEVIEW PTR
        LOCAL pTVDI         AS TV_DISPINFO PTR
        LOCAL lpNmh         AS NMHDR PTR
        STATIC hTreeItem    AS LONG
        LOCAL lTime1        AS LONG
        LOCAL lTime2        AS LONG
        LOCAL lCount        AS LONG
        LOCAL TVtxt         AS STRING
        STATIC hChild       AS LONG
        STATIC hSectionFlag AS LONG
        LOCAL kKey          AS TV_KEYDOWN PTR
        STATIC kKeylastkey  AS LONG
        SELECT CASE AS LONG CBMSG
    
            CASE %WM_INITDIALOG
    
                ' Pre DIM the array for encreased speed.
                'DIM TVTextArray(100000)
    
                ' Kick it in motion
                POSTMESSAGE CBHNDL, %WM_USER + 1000, 0, 0
    
            CASE %WM_USER + 1000
    
                ' Fill the TreeView with Test Data doing x loops
                lTime1 = TIMER
                lCount = FillTreeViewTest( 1000 )
                lTime2 = TIMER
    
                MSGBOX FORMAT$(lCount) & " items added to the TreeView in ~" & FORMAT$(lTime2 - lTime1) & " sec.",,"Info"
    
            CASE %WM_NOTIFY
    
                lpNmh = CBLPARAM
                lpTV = CBLPARAM
    
                SELECT CASE @lpNmh.idFrom
    
                    CASE %ID_TREEVIEW
    
                        SELECT CASE @lpNmh.Code
    
                            ' Get the text in TVTextArray to be displayed.
                            CASE %TVN_GETDISPINFO
    
                                pTVDI = CBLPARAM
    
                                IF (@pTVDI.item.mask AND %TVIF_TEXT) THEN
                                    POKE$ @pTVDI.item.pszText, LEFT$( TVTextArray( @pTVDI.item.lParam ), @pTVDI.item.cchTextMax)
                                END IF
    
                                FUNCTION = 0
                                EXIT FUNCTION
    
                            CASE %TVN_KEYDOWN
                              kKey = CBLPARAM
                              kKeylastkey = @kKey.wVKey
                            CASE %TVN_SELCHANGING
                            ' Get and select item when [+] is clicked
                            CASE %TVN_SELCHANGED
                                lpTV = CBLPARAM
                                hTreeItem = @lpTV.ItemNew.hItem
                                TVtxt$ = TVGetText(hTreeView, hTreeItem)
                                IF INSTR(TVtxt$,"Parent") > 0 AND kKeylastkey <> 39 AND kKeylastkey <> 38 AND kKeylastkey <> 37 THEN
                                  hChild = SendMessage(hTreeView, %TVM_GETNEXTITEM, %TVGN_CHILD, hTreeItem)
                                  TreeView_SelectItem(hTreeView, hChild)
                                ELSEIF INSTR(TVtxt$,"Parent") > 0 AND kKeylastkey = 38 THEN
                                  hChild = SendMessage(hTreeView, %TVM_GETNEXTITEM, %TVGN_PREVIOUSVISIBLE, hTreeItem)
                                  TreeView_SelectItem(hTreeView, hChild)
                                ELSEIF INSTR(TVtxt$,"Parent") > 0 AND kKeylastkey = 37 THEN
                                  TreeView_Expand(hTreeView,hTreeItem,%TVE_COLLAPSE)
                                ELSEIF INSTR(TVtxt$,"Parent") > 0 AND kKeylastkey = 39 THEN
                                  TreeView_Expand(hTreeView,hTreeItem,%TVE_EXPAND)
                                END IF
                                kKeylastkey = 0
                            CASE %TVN_ITEMEXPANDED
                                ' Get selected item
                                hTreeItem = @lpTV.ItemNew.hItem
    
                                ' Select the item where [+] was clicked
                                'TreeView_Select(hTreeView, hTreeItem, %TVGN_CARET)
                                FUNCTION = 0
                                EXIT FUNCTION
    
                        END SELECT
    
                END SELECT
    
            CASE %WM_COMMAND
    
                SELECT CASE AS LONG CBCTL
    
                    CASE %IDCANCEL
    
                        ' End
                        DIALOG END CBHNDL, 0
    
                END SELECT
    
            CASE %WM_DESTROY
    
                ' Nuke the array just to make sure
                ERASE TVTextArray()
    
        END SELECT
    
    END FUNCTION
    
    '==============================================================================
    FUNCTION PBMAIN() AS LONG
        LOCAL hDlg AS DWORD
    
        DIALOG NEW 0, "Skip Section Headers", , , 300, 260, _
            %WS_CHILD OR %WS_SYSMENU OR %WS_MAXIMIZEBOX OR %WS_MINIMIZEBOX OR %WS_CAPTION TO hDlg
    
        CONTROL ADD "SysTreeView32", hDlg, %ID_TREEVIEW, "", 10, 10, 280, 245, _
            %WS_CHILD OR %WS_VISIBLE OR %WS_CLIPCHILDREN _
            OR %TVS_HASBUTTONS _       '+/- buttons for parent nodes with children
            OR %TVS_HASLINES _         'shows connector lines & buttons for tree structure (below the root)
            OR %TVS_LINESATROOT _      'shows connector lines & buttons at root level of tree structure
            OR %TVS_DISABLEDRAGDROP _  'does not send dragdrop notifications
            OR %TVS_SHOWSELALWAYS _    'Show selected item even when treeview does NOT have focus
            OR %TVS_TRACKSELECT _      'Underlines item where mouse cursor points
            , %WS_EX_CLIENTEDGE
    
        CONTROL HANDLE hDlg, %ID_TREEVIEW TO hTreeView
    
        DIALOG SHOW MODAL hDlg CALL DialogProc
    
    END FUNCTION

    Leave a comment:


  • Michael Mattias
    replied
    >CONTROL ADD "SysTreeView32", hDlg, %ID_TREEVIEW, "", 10, 10, 280, 245,

    As a general rule, CBCTL is meaningless when the control is added with CONTROL ADD "classname" because DDT has no way knowing how "classname" sends its notification messages to the dialog's CALLBACK FUNCTION. Does it use WM_COMMAND? WM_NOTIFY? Something else?

    Essentially all you can count on being valid in this case is CBHNDL, CBMSG, CBLPARAM and CBWPARAM.

    Lots of things might "work" but I must refer you, too, to the current thread on "forgiving" at http://www.powerbasic.com/support/pb...ad.php?t=40098

    MCM

    Leave a comment:


  • BOB MECHLER
    replied
    That part was from the sample code I borrowed, but you're right it needs to be idFrom. It wasn't causing a problem though in this sample.

    Bob Mechler

    Leave a comment:


  • Michael Mattias
    replied
    Code:
    lpNmh = CBLPARAM
                lpTV = CBLPARAM
    
                SELECT CASE [B][COLOR="Red"]CBCTL[/COLOR][/B]
    CBCTL is not the correct way to identify control ID under WM_NOTIFY.

    You want ot use @lpnmh.idFrom or the new CB.NMID

    Leave a comment:


  • BOB MECHLER
    replied
    I found this code and modified a portion under TVN_SELCHANGED to illustrate what I want to do. I'm about halfway there. I can tell when I'm on a 'Parent or Section Header node based on the text and don't want the user to be able to highlight it since it won't be doing anything in the production code. It is however supposed to allow for expanding and collapsing the child items level.

    Initially when you click on any of the parent nodes it will currently detect that and get the first child, expanding the node as needed. I've also trapped the up and down arrow keys to allow the up and down arrow to 'skip' over the parent node. The only thing I lack is the ability to close up the node. I've locked that action from happening somehow. I'm thinking I'll need to do that in the TVN_SELCHANGING EVENT but I'm not sure how to do that.

    Any help please

    Bob Mechler


    Code:
    'MESSAGE http://www.powerbasic.com/support/forums/Forum7/HTML/003114.html
    'FORUM:  Source Code
    'TOPIC:  Basic TreeView LPStr_TextCallBack Demo
    'NAME:   Tonny Bjorn, Member
    'DATE:   March 05, 2007 09:51 AM
    
    
    '==============================================================================
    ' Basic demo on using large amounts of data into TreeView using %LPSTR_TEXTCALLBACK
    ' and %TVN_GETDISPINFO for better performance. NB: %LVN_GETDISPINFO for ListView
    '------------------------------------------------------------------------------
    ' Used Compiler: PB/WIN 8.03
    ' WIN32API Date: 01*Feb*2005 (Updated 27 January 2005)
    ' COMMCTRL Date: 01*Feb*2005 (Updated 27 October 2003)
    ' Prg tested on: Windows 2000 SP3, Windows XP Pro SP2
    '==============================================================================
    #COMPILE EXE
    #DIM ALL
    
    %USEMACROS = 1
    
    #INCLUDE "WIN32API.INC"
    #INCLUDE "COMMCTRL.INC"
    
    '==============================================================================
    %ID_TREEVIEW            = 100
    
    '==============================================================================
    GLOBAL hTreeView        AS LONG     ' TreeView Handle
    GLOBAL TVTextArray()    AS STRING   ' TreeView Text Label Storage
    
    '==============================================================================
    ' Get the text from the selected item in the TreeView
    '------------------------------------------------------------------------------
    ' hTree     - TreeView Handle
    ' hTVItem   - Selected TreeView item
    '==============================================================================
    FUNCTION TVGetText(BYVAL hTree AS LONG, BYVAL hTVItem 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)
        FUNCTION = zText
    END FUNCTION
    
    '==============================================================================
    ' Insert an item in the TreeView using LPSTR_TEXTCALLBACK for improved speed
    '------------------------------------------------------------------------------
    ' hTree     - TreeView handle
    ' hParent   - Handle for position type (root, parent child) in the tree
    ' lItemNum  - Indicator coresponding to the text in the TVTextArray for the TreeView
    ' lTextMax  - Length of the string being added
    '==============================================================================
    FUNCTION TVInsertLPSTRItem(BYVAL hTree AS LONG, BYVAL hParent AS LONG, BYVAL lItemNum AS LONG, BYVAL lTextMax AS LONG) AS LONG
        LOCAL tTVInsert   AS TV_INSERTSTRUCT
        LOCAL tTVItem     AS TV_ITEM
        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 OR %TVIF_PARAM
        tTVInsert.Item.Item.pszText = %LPSTR_TEXTCALLBACK
        tTVInsert.Item.Item.cchTextMax = lTextMax
        tTVInsert.Item.Item.lParam  = lItemNum
        FUNCTION = TreeView_InsertItem(hTree, tTVInsert)
    END FUNCTION
    
    '==============================================================================
    FUNCTION FillTreeViewTest(BYVAL lCount AS LONG) AS LONG
        LOCAL hTopRoot  AS DWORD
        LOCAL hRoot     AS DWORD
        LOCAL hParent   AS DWORD
        LOCAL hChild    AS DWORD
        LOCAL g         AS LONG
        LOCAL h         AS LONG
        LOCAL i         AS LONG
        LOCAL j         AS LONG
        LOCAL k         AS LONG
        LOCAL sBuffer   AS STRING
    
        k = 0
    
        ' =======================================================================
        ' Test if array is big enough to hold string, else REDIM and add a
        ' little extra to minimize slow redim process time. The extra array
        ' overhead is balanced out by improved speed.
        IF UBOUND(TVTextArray) < k THEN REDIM PRESERVE TVTextArray(k + 100)
    
        ' Add string to array for %LPSTR_TEXTCALLBACK
        TVTextArray(k) = "Root"
    
        ' Insert the item in the TreeView
        hTopRoot = TVInsertLPSTRItem(hTreeView, 0, k, LEN(TVTextArray(k)))
        ' =======================================================================
    
        FOR i = 1 TO lCount
    
            ' Add Parent
            sBuffer = "Parent Pos #" & FORMAT$(i)
    
            INCR k
    
            IF UBOUND(TVTextArray) < k THEN REDIM PRESERVE TVTextArray(k + 100)
    
            TVTextArray(k) = sBuffer
    
            hRoot = TVInsertLPSTRItem(hTreeView, hTopRoot, k, LEN(TVTextArray(k)))
    
            ' Add Childs
            FOR j = 1 TO 5
    
                INCR k
    
                IF UBOUND(TVTextArray) < k THEN REDIM PRESERVE TVTextArray(k + 100)
    
                TVTextArray(k) = "Child1 Pos #" & FORMAT$(j)
    
                hParent = TVInsertLPSTRItem(hTreeView, hRoot, k, LEN(TVTextArray(k)))
    
                ' Add Childs
                FOR h = 1 TO 5
    
                    INCR k
    
                    IF UBOUND(TVTextArray) < k THEN REDIM PRESERVE TVTextArray(k + 100)
    
                    TVTextArray(k) = "Child2 Pos #" & FORMAT$(h)
    
                    hChild = TVInsertLPSTRItem(hTreeView, hParent, k, LEN(TVTextArray(k)))
    
                    ' Add Subs
                    FOR g = 1 TO 3
    
                        INCR k
    
                        IF UBOUND(TVTextArray) < k THEN REDIM PRESERVE TVTextArray(k + 100)
                        TVTextArray(k) = "Sub Pos #" & FORMAT$(g)
                        TVInsertLPSTRItem(hTreeView, hChild, k, LEN(TVTextArray(k)))
    
                    NEXT
    
                NEXT
    
            NEXT
    
        NEXT
    
        FUNCTION = k
    
        DIALOG DOEVENTS
    
    END FUNCTION
    
    '==============================================================================
    CALLBACK FUNCTION DialogProc()
        LOCAL lpTV          AS NM_TREEVIEW PTR
        LOCAL pTVDI         AS TV_DISPINFO PTR
        LOCAL lpNmh         AS NMHDR PTR
        STATIC hTreeItem    AS LONG
        LOCAL lTime1        AS LONG
        LOCAL lTime2        AS LONG
        LOCAL lCount        AS LONG
        LOCAL TVtxt         AS STRING
        STATIC hChild       AS LONG
        STATIC hSectionFlag AS LONG
        LOCAL kKey          AS TV_KEYDOWN PTR
    [COLOR="Red"]    STATIC kKeylastkey  AS LONG[/COLOR]    
        SELECT CASE AS LONG CBMSG
    
            CASE %WM_INITDIALOG
    
                ' Pre DIM the array for encreased speed.
                'DIM TVTextArray(100000)
    
                ' Kick it in motion
                POSTMESSAGE CBHNDL, %WM_USER + 1000, 0, 0
    
            CASE %WM_USER + 1000
    
                ' Fill the TreeView with Test Data doing x loops
                lTime1 = TIMER
                lCount = FillTreeViewTest( 1000 )
                lTime2 = TIMER
    
                MSGBOX FORMAT$(lCount) & " items added to the TreeView in ~" & FORMAT$(lTime2 - lTime1) & " sec.",,"Info"
    
            CASE %WM_NOTIFY
    
                lpNmh = CBLPARAM
                lpTV = CBLPARAM
    
                SELECT CASE CBCTL
    
                    CASE %ID_TREEVIEW
    
                        SELECT CASE @lpNmh.Code
    
                            ' Get the text in TVTextArray to be displayed.
                            CASE %TVN_GETDISPINFO
    
                                pTVDI = CBLPARAM
    
                                IF (@pTVDI.item.mask AND %TVIF_TEXT) THEN
                                    POKE$ @pTVDI.item.pszText, LEFT$( TVTextArray( @pTVDI.item.lParam ), @pTVDI.item.cchTextMax)
                                END IF
    
                                FUNCTION = 0
                                EXIT FUNCTION
    
                            ' The TreeView is changing
    [COLOR="Red"]                        CASE %TVN_KEYDOWN
                              kKey = CBLPARAM
                              kKeylastkey = @kKey.wVKey[/COLOR]                        CASE %TVN_SELCHANGING
    
                                FUNCTION = 0
                                EXIT FUNCTION
    
                            ' Get and select item when [+] is clicked
                            CASE %TVN_SELCHANGED
    [COLOR="red"]                            lpTV = CBLPARAM
                                hTreeItem = @lpTV.ItemNew.hItem
                                TVtxt$ = TVGetText(hTreeView, hTreeItem)
                                IF INSTR(TVtxt$,"Parent") > 0 AND kKeylastkey <> 38 THEN
                                  hChild = SendMessage(hTreeView, %TVM_GETNEXTITEM, %TVGN_CHILD, hTreeItem)
                                  TreeView_SelectItem(hTreeView, hChild)
                                ELSEIF INSTR(TVtxt$,"Parent") > 0 AND kKeylastkey = 38 THEN
                                  hChild = SendMessage(hTreeView, %TVM_GETNEXTITEM, %TVGN_PREVIOUSVISIBLE, hTreeItem)
                                  TreeView_SelectItem(hTreeView, hChild)
                                END IF
                                kKeylastkey = 0[/COLOR]                        
                            CASE %TVN_ITEMEXPANDED
    
                                ' Get selected item
                                hTreeItem = @lpTV.ItemNew.hItem
    
                                ' Select the item where [+] was clicked
                                TreeView_Select(hTreeView, hTreeItem, %TVGN_CARET)
    
                                FUNCTION = 0
                                EXIT FUNCTION
    
                        END SELECT
    
                END SELECT
    
            CASE %WM_COMMAND
    
                SELECT CASE AS LONG CBCTL
    
                    CASE %IDCANCEL
    
                        ' End
                        DIALOG END CBHNDL, 0
    
                END SELECT
    
            CASE %WM_DESTROY
    
                ' Nuke the array just to make sure
                ERASE TVTextArray()
    
        END SELECT
    
    END FUNCTION
    
    '==============================================================================
    FUNCTION PBMAIN() AS LONG
        LOCAL hDlg AS DWORD
    
        DIALOG NEW 0, "LPSTR_TEXTCALLBACK TreeView Demo", , , 300, 260, _
            %WS_CHILD OR %WS_SYSMENU OR %WS_MAXIMIZEBOX OR %WS_MINIMIZEBOX OR %WS_CAPTION TO hDlg
    
        CONTROL ADD "SysTreeView32", hDlg, %ID_TREEVIEW, "", 10, 10, 280, 245, _
            %WS_CHILD OR %WS_VISIBLE OR %WS_CLIPCHILDREN _
            OR %TVS_HASBUTTONS _       '+/- buttons for parent nodes with children
            OR %TVS_HASLINES _         'shows connector lines & buttons for tree structure (below the root)
            OR %TVS_LINESATROOT _      'shows connector lines & buttons at root level of tree structure
            OR %TVS_DISABLEDRAGDROP _  'does not send dragdrop notifications
            OR %TVS_SHOWSELALWAYS _    'Show selected item even when treeview does NOT have focus
            , %WS_EX_CLIENTEDGE
            'OR %TVS_TRACKSELECT _      'Underlines item where mouse cursor points
    
        CONTROL HANDLE hDlg, %ID_TREEVIEW TO hTreeView
    
        DIALOG SHOW MODAL hDlg CALL DialogProc
    
    END FUNCTION

    Leave a comment:


  • Michael Mattias
    replied
    Return value/Exit function?

    [from TVN_SELCHANGED]
    ...
    Return Value

    The return value is ignored.
    As far as selecting, I don't think you want the drop highlight flag....

    flag
    Action flag. This parameter can be one of the following values:
    TVGN_CARET
    Sets the selection to the given item. The control's parent window receives the TVN_SELCHANGING and TVN_SELCHANGED notification messages.
    And expanding?
    Remarks

    If the specified item is the child of a collapsed parent item, the parent's list of child items is expanded to reveal the specified item. In this case, the parent window receives the TVN_ITEMEXPANDING and TVN_ITEMEXPANDED notification messages.
    I think changing that flag ought to do wonders for you.

    MCM

    Leave a comment:


  • BOB MECHLER
    replied
    Helpful info.
    htree&(2) is what I used not knowing how to get it using @lpnmh.hWndfrom.

    I put in the expand part because it didn't auto expand for me.

    After some testing, this code works about half the time. It sometimes fires twice and I get the second child down and the first child is gone so I'll just leave it a while and test in a test area.

    I was also unsure about the EXIT FUNCTION. I was trying to get it to go to the first child then assumed the %TVN_SELCHANGED would fire again. Not real clear on how I can programmatically walk the tree without getting into trouble.

    Thanks,

    Bob Mechler

    Leave a comment:


  • Michael Mattias
    replied
    The treeview_Expand should not be needed, as TreeView_select should automatically expand the item if necessary to make it visible.

    >IF TreeView_GetParent(htree&(2),@lpTV.ItemNew.hItem)

    What is hTree&(2)?

    When processing WM_NOTIFY, @lpnmh.hWndfrom is a handle to the control sending the message; that is, there is n need to maintain that in a STATIC or GLOBAL array.

    If you need a handle to another treeview control on the screen while processing the message from this treeview, you can always use GetDlgItem(hWnd,%ID_OTHER_TREEVIEW).

    In window procedures, you virtually never have to maintain window handles in STATIC or GLOBAL variables.. beacuse given the Hwnd passed as parm one to callback, you can get just about anywhere you need. (the plethora of "GLOBAL hDlg" in the help file notwithstanding)

    MCM

    Leave a comment:


  • BOB MECHLER
    replied
    This does what I want. The double-clicking of the root node toggles between expanded and/or collapsed but the single click of the + or the - doesn't respond. Might be ok this way, just checking.

    Code:
      IF (@lpNmh.Code = %TVN_SELCHANGED) AND (@lpNmh.idFrom = %ID_TREE2) THEN
        lpTV = CBLPARAM
        IF TreeView_GetParent(htree&(2),@lpTV.ItemNew.hItem) = 0 THEN 'on a header item
          SetWindowText hdlg,"On a header item"     
          TreeView_Expand(hTree&(2),@lpTV.ItemNew.hItem,%TVE_EXPAND)
          TreeView_Select(htree&(2),TreeView_GetNextItem(htree&(2),@lpTV.ItemNew.hItem,%TVGN_CHILD),%TVGN_DROPHILITE)
          EXIT FUNCTION
        ELSE  
          SetWindowText hdlg,"On a child item"     
        END IF
    END IF
    Bob Mechler

    Leave a comment:


  • Michael Mattias
    replied
    Is it possible to cause the item navigated to or single clicked
    Code:
     WM_NOTIFY/TVN_SELCHANGED
    
    If new_selection = "Root item" THEN 
       Treeview_Select (First child of same) 
    ....
    MCM

    Leave a comment:


  • BOB MECHLER
    started a topic Treeview question

    Treeview question

    I'm using a treeview as a menu where the root level are really section headers and the nodes that call programs are in the first child level.

    Is it possible to cause the item navigated to or single clicked in the root level to auto move to the first child node and highlight it? A root node will always have child nodes.

    I would still like the normal behaviour of double-clicking the root node to open or close the first level of child nodes.

    Bob Mechler
    Last edited by BOB MECHLER; 10 Mar 2009, 12:36 PM. Reason: More info
Working...
X