如何用递归方法在treeview中查找节点,并把这个节点选中和展开它. 100分在线等!!!

解决方案 »

  1.   

    http://www.yesky.com/484/1723984.shtml
    这是个用TreeView实现资源管理器的代码,其中展开给定目录的功能用到了递归,正好是楼主要的,楼主自己研究一下吧。
      

  2.   

    VERSION 5.00
    Begin VB.Form FrmTreeSearch 
       BorderStyle     =   3  'Fixed Dialog
       Caption         =   "查找"
       ClientHeight    =   1395
       ClientLeft      =   45
       ClientTop       =   330
       ClientWidth     =   4260
       ControlBox      =   0   'False
       LinkTopic       =   "Form1"
       LockControls    =   -1  'True
       MaxButton       =   0   'False
       MinButton       =   0   'False
       ScaleHeight     =   1395
       ScaleWidth      =   4260
       ShowInTaskbar   =   0   'False
       StartUpPosition =   3  'Windows Default
       Begin VB.CheckBox Check1 
          Caption         =   "模糊"
          Height          =   210
          Left            =   120
          TabIndex        =   1
          Top             =   525
          Width           =   720
       End
       Begin VB.Frame Frame1 
          Caption         =   "方向"
          Height          =   735
          Left            =   960
          TabIndex        =   9
          Top             =   495
          Width           =   2205
          Begin VB.OptionButton Option4 
             Caption         =   "向下"
             Height          =   390
             Left            =   1170
             TabIndex        =   5
             Top             =   210
             Width           =   855
          End
          Begin VB.OptionButton Option3 
             Caption         =   "向上"
             Height          =   360
             Left            =   135
             TabIndex        =   4
             Top             =   225
             Width           =   765
          End
       End
       Begin VB.CommandButton cmdCancel 
          Caption         =   "取消"
          Height          =   375
          Left            =   3270
          TabIndex        =   7
          Top             =   690
          Width           =   915
       End
       Begin VB.CommandButton cmdNext 
          Caption         =   "下一个"
          Height          =   375
          Left            =   3285
          TabIndex        =   6
          Top             =   165
          Width           =   900
       End
       Begin VB.TextBox Text1 
          Height          =   330
          Left            =   945
          TabIndex        =   0
          Text            =   "Text1"
          Top             =   165
          Width           =   2190
       End
       Begin VB.OptionButton Option2 
          Caption         =   "用户"
          Height          =   195
          Left            =   120
          TabIndex        =   3
          Top             =   1020
          Width           =   750
       End
       Begin VB.OptionButton Option1 
          Caption         =   "部门"
          Height          =   195
          Left            =   120
          TabIndex        =   2
          Top             =   765
          Width           =   795
       End
       Begin VB.Label Label1 
          AutoSize        =   -1  'True
          Caption         =   "查找内容:"
          Height          =   195
          Left            =   120
          TabIndex        =   8
          Top             =   165
          Width           =   765
       End
    End
    Attribute VB_Name = "FrmTreeSearch"
    Attribute VB_GlobalNameSpace = False
    Attribute VB_Creatable = False
    Attribute VB_PredeclaredId = True
    Attribute VB_Exposed = False
      

  3.   

    Option ExplicitPrivate Sub Form_Load()
        Me.Top = (Screen.Height - Me.Height) / 2
        Me.Left = (Screen.Width - Me.Width) / 2
        Text1.text = FrmMain.TreeView1.SelectedItem.text
        If Left(FrmMain.TreeView1.SelectedItem.key, 1) = "U" Then
            Option2.Value = True
        Else
            Option1.Value = True
        End If
        Option4.Value = True
        Check1.Value = 1
        SendKeys "{Home}+{End}"
    End Sub'/////////////////////////////////////////////////////////////
    '///////////// cmd   func   //////////////////////////////////
    '/////////////////////////////////////////////////////////////Private Sub cmdNext_Click()
    On Error Resume Next
        Dim str As String
        Dim mode As Integer
        Dim way As Integer
        Dim user As Integer
        Dim node As node
        '------------
        str = Text1.text
        '------------
        Set node = FrmMain.TreeView1.SelectedItem
        '------------
        If Check1.Value = 0 Then '精确
            mode = 2
        ElseIf Check1.Value = 1 Then '模糊
            mode = 1
        Else
            MessageBox 0, "程序异常错误!,即将关闭!", "错误", MB_ICONHAND + MB_TASKMODAL
            g_blnQuit = True
            End
        End If
        '------------
        If Option1.Value = True Then '部门
            user = 2
        ElseIf Option2.Value = True Then '用户
            user = 1
        Else
            MessageBox 0, "程序异常错误!,即将关闭!", "错误", MB_ICONHAND + MB_TASKMODAL
            g_blnQuit = True
            End
        End If
        '------------
        If Option4.Value = True Then '向下
            way = 1    ElseIf Option3.Value = True Then '向上
            way = 2
        Else
            MessageBox 0, "程序异常错误!,即将关闭!", "错误", MB_ICONHAND + MB_TASKMODAL
            g_blnQuit = True
            End
        End If
        '------------回溯法
        If way = 1 Then
            If Not find_down(FrmMain.TreeView1, node, str, mode, user) Then
                MessageBox 0, "没有找到" & IIf(user = 2, "部门:", "用户:") & "  " & str, "警告", MB_ICONHAND
                Text1.SetFocus
                SendKeys "{Home}+{End}"
            End If
        Else
            If Not find_up(FrmMain.TreeView1, node, str, mode, user) Then
                MessageBox 0, "没有找到" & IIf(user = 2, "部门:", "用户:") & "  " & str, "警告", MB_ICONHAND
                Text1.SetFocus
                SendKeys "{Home}+{End}"
            End If
        End If
    End Sub
    Private Sub cmdCancel_Click()
        Unload Me
    End Sub'/////////////////////////////////////////////////////////////
    '///////////// other func   //////////////////////////////////
    '/////////////////////////////////////////////////////////////Private Function find_down(tvw As TreeView, nd As node, str As String, mode As Integer, user As Integer) As Boolean
        'mode  1 模糊 2 精确
        'user  1 用户 2 部门
        '---------------------
        Dim curLevel As Long, maxLevel As Long, i As Long
        Dim LevelInfo() As typLevelInfo, tmpLevelInfo As typLevelInfo
        Dim strKey As String
        Dim tmpNode As node, tmpNode_2 As node
        Set tmpNode = nd
        strKey = nd.key
        '---------------------
        Do Until TypeName(tmpNode) = "Nothing"
            i = 0
            Set tmpNode_2 = tmpNode
            Do
                i = i + 1
                Set tmpNode_2 = tmpNode_2.Previous
            Loop Until TypeName(tmpNode_2) = "Nothing"
            curLevel = curLevel + 1
            ReDim Preserve LevelInfo(curLevel) As typLevelInfo
            LevelInfo(curLevel).index = i
            LevelInfo(curLevel).key = tmpNode.key
            Set tmpNode = tmpNode.Parent
        Loop
        '-----倒序------------
        For i = 0 To UBound(LevelInfo) \ 2
            tmpLevelInfo = LevelInfo(i)
            LevelInfo(i) = LevelInfo(UBound(LevelInfo) - i)
            LevelInfo(UBound(LevelInfo) - i) = tmpLevelInfo
        Next i
        '--------------------
        maxLevel = curLevel
        Do
            
            If nd.key <> strKey Then
                If (mode = 1 And InStr(1, nd.text, str) <> 0) Or (mode = 2 And nd.text = str) Then '找到
                If (user = 1 And Left(nd.key, 1) = "U") Or (user = 2 And Left(nd.key, 1) = "A") Then '合理
                    nd.Selected = True: find_down = True: Exit Function
                End If
                End If
            End If
            '------
            Do Until LevelInfo(curLevel).index < nd.Children  '回溯,直到当前层有未查找节点
                Set nd = nd.Parent
                LevelInfo(curLevel).index = 0
                curLevel = curLevel - 1
                If curLevel = 0 Then Exit Function
            Loop
            '------
            If LevelInfo(curLevel).index = 0 Then             '当前层下一个节点
                Set nd = nd.Child
            Else
                Set nd = tvw.Nodes(LevelInfo(curLevel).key).Next
            End If
            LevelInfo(curLevel).key = nd.key
            LevelInfo(curLevel).index = LevelInfo(curLevel).index + 1
            curLevel = curLevel + 1
            If curLevel > maxLevel Then
                maxLevel = curLevel
                ReDim Preserve LevelInfo(maxLevel) As typLevelInfo
            End If
        Loop
    End Function
    Private Function find_up(tvw As TreeView, nd As node, str As String, mode As Integer, user As Integer) As Boolean
        
        'mode  1 模糊 2 精确
        'user  1 用户 2 部门
        '---------------------
        Dim curLevel As Long, maxLevel As Long, i As Long
        Dim LevelInfo() As typLevelInfo, tmpLevelInfo As typLevelInfo
        Dim strKey As String
        Dim fndNode As node '如果找到,则不是 "Nothing"
        strKey = nd.key '找到的strkey不算
        Set nd = nd.Root 'root找起
        ReDim Preserve LevelInfo(1) As typLevelInfo
        curLevel = 1: maxLevel = 1
        
        Do
            If nd.key <> strKey Then
                If (mode = 1 And InStr(1, nd.text, str) <> 0) Or (mode = 2 And nd.text = str) Then '找到
                If (user = 1 And Left(nd.key, 1) = "U") Or (user = 2 And Left(nd.key, 1) = "A") Then '合理
                    Set fndNode = nd
                End If
                End If
            Else
                Exit Do '从root向下找到了nd
            End If
            '------
            Do Until LevelInfo(curLevel).index < nd.Children  '回溯,直到当前层有未查找节点
                Set nd = nd.Parent
                LevelInfo(curLevel).index = 0
                curLevel = curLevel - 1
            Loop
            '------
            If LevelInfo(curLevel).index = 0 Then             '当前层下一个节点
                Set nd = nd.Child
            Else
                Set nd = tvw.Nodes(LevelInfo(curLevel).key).Next
            End If
            LevelInfo(curLevel).key = nd.key
            LevelInfo(curLevel).index = LevelInfo(curLevel).index + 1
            curLevel = curLevel + 1
            If curLevel > maxLevel Then
                maxLevel = curLevel
                ReDim Preserve LevelInfo(maxLevel) As typLevelInfo
            End If
        Loop
        
        If TypeName(fndNode) <> "Nothing" Then
            fndNode.Selected = True
            find_up = True
        Else
            find_up = False
        End If
    End Function
      

  4.   

    很早写的代码,回溯treeview, 同注册表的查找一样深度优先。
    可向上,向下找一个树的指定接点。
      

  5.   

    Public Type typLevelInfo '回溯法查找节点中.用于表示当前层的状态
        index As Long
        key As String
    End Type
      

  6.   

    选择“部门”,表示查找树枝上的指定文字, 选择“用户”, 表示查找叶子上的指定文字。
    为了表示树枝和叶子, 你的key要分别用A和U开头。
    这里的“部门”, “用户”, 你可以随便换成你想要的东西。你的树只要满足上面这个条件即可查询。回溯的效率要略高于递归
      

  7.   

    Private Sub TreeView1_NodeCheck(ByVal Node As MSComctlLib.Node)
    Dim I       As Integer
    Dim mNode   As Node
    If Node.Key <> "all" Then
        Label5.Caption = ""
        Select Case Left(Node.Key, 3)
            Case "all"
                If Node.Checked = True Then
                    StopAdd = IIf(List1.ListCount = 32, True, False)
                    If StopAdd Then
                        Label5.Caption = "已到达该组最大容量,无法继续添加!"
                        Exit Sub
                    End If
                    aaa Node, True
                Else
                    aaa Node, False
                End If
               case "cld"
                         ..............
            End Select
        Label4.Caption = "剩余  " & 32 - List1.ListCount & "  个未添加"End If
    End Sub
    Private Sub aaa(ByVal sNode As Node, ByVal IsAddProduce As Boolean)
    Dim mNode   As Node
    For Each mNode In TreeView1.Nodes
        If StopAdd Then Exit Sub
        If mNode.Key <> "all" Then
        If mNode.Parent.Key = sNode.Key Then
            Select Case Left(mNode.Key, 3)
                Case "all"
                    mNode.Checked = IsAddProduce ' True
                    mNode.Expanded = IsAddProduce ' True
                    aaa mNode, IsAddProduce
                case "cld"
            End Select
        End If
        End If
    Next
    End Sub这是当把父节点的checkbox的值修改的时候同时修改其下面所有节点的值,
    并且是其下的节点也是父节点则展开
    类似于杀毒软件你勾选要杀毒的文件夹时的操作
      

  8.   

    我正好要用这个功能,能否提供源码?[email protected]
      

  9.   

    下面是一个递归例子,想要其他功能自己修改Option ExplicitPrivate Sub Form_Load()
        With TreeView1
            .Nodes.Add , , "Parent1", "Test1"
            .Nodes.Add "Parent1", tvwChild, "Child1", "Test_CH1"
            .Nodes.Add "Parent1", tvwChild, "Child2", "Test_CH2"
            .Nodes.Add "Parent1", tvwChild, "Child3", "Test_CH3"
            .Nodes.Add "Child3", tvwChild, "Child_33", "Test_CH3_CH3"
            .Nodes.Add "Parent1", tvwChild, "Child4", "Test_CH4"
            .Nodes.Add "Parent1", tvwChild, "Parent2", "Test2"
            .Nodes.Add "Parent2", tvwChild, "Child11", "Test_CH1"
            .Nodes.Add "Parent2", tvwChild, "Child22", "Test_CH2"
            .Nodes.Add "Parent2", tvwChild, "Child33", "Test_CH3"
            .Nodes.Add "Parent2", tvwChild, "Child44", "Test_CH4"
            .Checkboxes = True
            .LineStyle = tvwTreeLines
        End With
        NodeAllExpanded TreeView1
    End Sub
    Private Sub TreeView1_NodeCheck(ByVal Node As MSComctlLib.Node)
        Call AllChildSynchro(Node)
        Call AllMaterSynchro(Node)
    End Sub
    '// -选中下级-
    Private Sub AllChildSynchro(ByVal NodeChoose As Object)
        On Error Resume Next
        Dim lNextLoop As Long
        Dim ObjChildren As Object
        If CBool(NodeChoose.Children > 0) Then
            Set ObjChildren = NodeChoose.Child
            For lNextLoop = 1 To NodeChoose.Children
                ObjChildren.Checked = NodeChoose.Checked
                If ObjChildren.Children > 0 Then Call AllChildSynchro(ObjChildren)
                Set ObjChildren = ObjChildren.Next
            Next lNextLoop
        End If
    End Sub'// -取消上级-
    Private Sub AllMaterSynchro(ByVal NodeChoose As Object)
        On Error Resume Next
        If Not NodeChoose.Checked Then If TypeName(NodeChoose.Parent) = "INode" Then NodeChoose.Parent.Checked = False
        If Not NodeChoose.Checked Then If TypeName(NodeChoose.Parent) = "INode" Then Call AllMaterSynchro(NodeChoose.Parent)
    End Sub'// -节点张开-
    Private Sub NodeAllExpanded(ByVal ObjTvw As Object)
        On Error Resume Next
        Dim ObjChild As Object
        For Each ObjChild In ObjTvw.Nodes
            ObjChild.Expanded = IIf(ObjChild.Key = ObjChild.Root.Key, False, True)
            ObjChild.Root.Expanded = IIf(ObjChild.Key = ObjTvw.Nodes(ObjTvw.Nodes.Count).Key, True, False)
        Next ObjChild
    End Sub