Paurths
asked on
recursive - can this be done?
hi,
i have table that holds all the folders for a drive.
The table is made up like this:
FolderID (autonumber - Pr.Key)
Foldername (name of the folder...)
FolderLevel (C: = 0, Winnt = 1, System32 = 2, etc)
FolderParentID (FolderID of the parentfolder, if Winnt
has folderid 15, then system32 will
have 15 as folderparentID)
this way i am able to use this table several times in one query to show a folder-structure.
Another table holds the nt-security-settings for each folder (with the local and global groups)
but, u guessed, this is not exactly a nice way of working
so i was thinking of loading this into a treeview,
and i assume i will need some sort of recursive function(s) for it to accomplish.
is this correct?
if so, has anyone have any experience with this kind of thing?
again, if so, any directions...?
cheers
Ricky
i have table that holds all the folders for a drive.
The table is made up like this:
FolderID (autonumber - Pr.Key)
Foldername (name of the folder...)
FolderLevel (C: = 0, Winnt = 1, System32 = 2, etc)
FolderParentID (FolderID of the parentfolder, if Winnt
has folderid 15, then system32 will
have 15 as folderparentID)
this way i am able to use this table several times in one query to show a folder-structure.
Another table holds the nt-security-settings for each folder (with the local and global groups)
but, u guessed, this is not exactly a nice way of working
so i was thinking of loading this into a treeview,
and i assume i will need some sort of recursive function(s) for it to accomplish.
is this correct?
if so, has anyone have any experience with this kind of thing?
again, if so, any directions...?
cheers
Ricky
In addition:
What do you want to do with hidden and system directories?
What does the user need to do? I ask this question because the Treeview control can slow your application needlessly if the user doesn't need to access this information.
What do you want to do with hidden and system directories?
What does the user need to do? I ask this question because the Treeview control can slow your application needlessly if the user doesn't need to access this information.
ASKER
hi akimark,
actually, i am still developing this program,
it has all (i hope) the issues about network.
routers, outlets, patchpanel, computers, printers, printservers (jet-direct and axis), desks, users, devisions, locations, local groups, global groups, etc...
this is only a small part of the entire program.
What i would like to do is:
if i could fill a treeview with all the folders, click on a node (e.g. a folder on a shared folder) immediatly know what groups, users, have what permissions.
I know i can retrieve this information in my form where the folders are shown/added.
I was just wondering if it can be done. (i would probably be the only person on this planet using this program, but i figured it would be good excercice...)
cheers
Ricky
actually, i am still developing this program,
it has all (i hope) the issues about network.
routers, outlets, patchpanel, computers, printers, printservers (jet-direct and axis), desks, users, devisions, locations, local groups, global groups, etc...
this is only a small part of the entire program.
What i would like to do is:
if i could fill a treeview with all the folders, click on a node (e.g. a folder on a shared folder) immediatly know what groups, users, have what permissions.
I know i can retrieve this information in my form where the folders are shown/added.
I was just wondering if it can be done. (i would probably be the only person on this planet using this program, but i figured it would be good excercice...)
cheers
Ricky
The quickest/easiest development effort will use a Directory (intrinsic) control. When the user selects a directory, you gather the permissions and display them.
If you gather all the permissions, you can either loop through them, looking for candidates with the LIKE operator, or place them in a table and use SQL with a WHERE LIKE search criteria.
You will possibly have several rules that will cascade (apply) to the selected directory.
If you gather all the permissions, you can either loop through them, looking for candidates with the LIKE operator, or place them in a table and use SQL with a WHERE LIKE search criteria.
You will possibly have several rules that will cascade (apply) to the selected directory.
Dim ParentFolder as Scripting.Folder
Dim oFolder as Scripting.Folder
Private Sub Form_Load()
Dim oFSO as Scripting.FileSystemObject
Set oFolder = oFSO.GetFolder("your\path" )
Call DoTree(oFolder)
End Sub
Private Function DoTree(oFolder as Scripting.Folder)
For Each Folder In oFolder.Folders
'Code to Process the folder
Call DoTree(oFolder)
Next
End Function
Dim oFolder as Scripting.Folder
Private Sub Form_Load()
Dim oFSO as Scripting.FileSystemObject
Set oFolder = oFSO.GetFolder("your\path"
Call DoTree(oFolder)
End Sub
Private Function DoTree(oFolder as Scripting.Folder)
For Each Folder In oFolder.Folders
'Code to Process the folder
Call DoTree(oFolder)
Next
End Function
Here is a snippet I just did in an Access Module (referencing mscomctl.ocx) for loading an employee hierachy from the CEO down..
This assumes you have an MSAccess table called "tblEmp"
Fields:
EmpID (Long)
EmpName (Text)
ParentEmpID (Long)
Whack the following functions in a vb module or form class and call the function:
BuldTree TreeView1
in Form_Load event
Change the following code to loop your FileSystemObjects instead of the tblEmp table records... good luck!
Option Explicit
Public Sub BuildTree(oTreeView As TreeView)
Dim sql As String
Dim rs As Recordset
Dim NodX As Node
On Error GoTo ET
' With oTreeView
' .Font = 1 ' .Font = "Tahoma"
' .Font.Size = "12"
' .Font.Bold = True
' '.Indentation = "500"
' .LabelEdit = False
' '.LineStyle = 1
' '.Style = 7
' '.FullRowSelect = True
' End With
'The following comments is a sample of adding nodes to the tree
' Set nodX = oTreeView.Nodes.Add(, , "R", "Root")
' Set nodX = oTreeView.Nodes.Add("R", tvwChild, "C1", "Child 1")
' Set nodX = oTreeView.Nodes.Add("R", tvwChild, "C2", "Child 2")
' Set nodX = oTreeView.Nodes.Add("R", tvwChild, "C3", "Child 3")
' Set nodX = oTreeView.Nodes.Add("R", tvwChild, "C4", "Child 4")
' Set nodX = oTreeView.Nodes.Add("C4", tvwChild, "C5", "Child 5")
' Set nodX = oTreeView.Nodes.Add("C5", tvwChild, "C6", "Child 6")
' nodX.EnsureVisible
'Add Parent Root Node ie. CEO
'assume CEO's EmpID=1
Set NodX = oTreeView.Nodes.Add(, , "Key=1", DLookup("EmpName", "tblEmp", "EmpID = 1"))
AddChildNodes oTreeView, 1
NodX.Bold = True
NodX.ForeColor = 255
Exit Sub
ET:
MsgBox Err.Number & " - " & Err.Description, vbCritical
End Sub
Private Sub AddChildNodes(oTreeView As TreeView, EmpID As Integer)
Dim rs As Recordset
Dim sql As String
Dim NodX As Node
sql = "SELECT EmpID, EmpName, ParentEmpID"
sql = sql & " FROM tblEmp"
sql = sql & " WHERE ParentEmpID = " & EmpID
sql = sql & " ORDER BY EmpID;"
Set rs = CurrentDb.OpenRecordset(sq l, dbOpenForwardOnly)
Do Until rs.EOF
Set NodX = oTreeView.Nodes.Add("Key=" & EmpID, tvwChild, "Key=" & rs!EmpID, rs!EmpName)
AddChildNodes oTreeView, rs!EmpID
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
End Sub
Public Sub DelTree(oTreeView As TreeView)
Do While oTreeView.Nodes.Count > 0
oTreeView.Nodes.Remove (1)
Loop
End Sub
This assumes you have an MSAccess table called "tblEmp"
Fields:
EmpID (Long)
EmpName (Text)
ParentEmpID (Long)
Whack the following functions in a vb module or form class and call the function:
BuldTree TreeView1
in Form_Load event
Change the following code to loop your FileSystemObjects instead of the tblEmp table records... good luck!
Option Explicit
Public Sub BuildTree(oTreeView As TreeView)
Dim sql As String
Dim rs As Recordset
Dim NodX As Node
On Error GoTo ET
' With oTreeView
' .Font = 1 ' .Font = "Tahoma"
' .Font.Size = "12"
' .Font.Bold = True
' '.Indentation = "500"
' .LabelEdit = False
' '.LineStyle = 1
' '.Style = 7
' '.FullRowSelect = True
' End With
'The following comments is a sample of adding nodes to the tree
' Set nodX = oTreeView.Nodes.Add(, , "R", "Root")
' Set nodX = oTreeView.Nodes.Add("R", tvwChild, "C1", "Child 1")
' Set nodX = oTreeView.Nodes.Add("R", tvwChild, "C2", "Child 2")
' Set nodX = oTreeView.Nodes.Add("R", tvwChild, "C3", "Child 3")
' Set nodX = oTreeView.Nodes.Add("R", tvwChild, "C4", "Child 4")
' Set nodX = oTreeView.Nodes.Add("C4", tvwChild, "C5", "Child 5")
' Set nodX = oTreeView.Nodes.Add("C5", tvwChild, "C6", "Child 6")
' nodX.EnsureVisible
'Add Parent Root Node ie. CEO
'assume CEO's EmpID=1
Set NodX = oTreeView.Nodes.Add(, , "Key=1", DLookup("EmpName", "tblEmp", "EmpID = 1"))
AddChildNodes oTreeView, 1
NodX.Bold = True
NodX.ForeColor = 255
Exit Sub
ET:
MsgBox Err.Number & " - " & Err.Description, vbCritical
End Sub
Private Sub AddChildNodes(oTreeView As TreeView, EmpID As Integer)
Dim rs As Recordset
Dim sql As String
Dim NodX As Node
sql = "SELECT EmpID, EmpName, ParentEmpID"
sql = sql & " FROM tblEmp"
sql = sql & " WHERE ParentEmpID = " & EmpID
sql = sql & " ORDER BY EmpID;"
Set rs = CurrentDb.OpenRecordset(sq
Do Until rs.EOF
Set NodX = oTreeView.Nodes.Add("Key="
AddChildNodes oTreeView, rs!EmpID
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
End Sub
Public Sub DelTree(oTreeView As TreeView)
Do While oTreeView.Nodes.Count > 0
oTreeView.Nodes.Remove (1)
Loop
End Sub
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
I wrote a form to do pretty much what you are asking. First off, yes, you can use recursion to go through all folders and load them into a treeview but a word of warning, it's very slow. You might not realize it but there are maybe hundreds or thousands of folders under Program Files, WINNT or some of the major folders. Even if you are just looking at directories, it can take a long time to load the tree.
I finally settled on loading one level at a time. So, first load all of the top level folders. Then, as you expand a folder just get it's direct child folders etc.
My example was also trying to track the folder sizes to help me locate disk-hogs. Here is some of the code. If you want the stuff that actually gets the directory size let me know. With a little tinkering this should do what you want.
Open a projet with a Treeview, a ListView, a Drive File List, name them appropriatly and paste in this code. You might have to comment out the calls to GetDirectorySize.
Private Sub Drive1_Change()
Dim oNode As Node
tvwDirectory.Nodes.Clear
Set Node = tvwDirectory.Nodes.Add(, , Left$(Drive1.Drive, 1) & ":", Left$(Drive1.Drive, 1) & ":", 1)
GetDirContents Left$(Drive1.Drive, 1) & ":"
tvwDirectory_NodeClick tvwDirectory.Nodes(1)
tvwDirectory.Nodes(1).Expa nded = True
End Sub
Private Sub Form_Load()
FormLoading = True
lvwDisplay.View = lvwReport
lvwDisplay.ColumnHeaders.A dd , , "Name", lvwDisplay.Width * 0.3, lvwColumnLeft
lvwDisplay.ColumnHeaders.A dd , , "Size", lvwDisplay.Width * 0.2, lvwColumnRight
lvwDisplay.ColumnHeaders.A dd , , "Relative", lvwDisplay.Width * 0.5, lvwColumnLeft
Drive1.Drive = "C:"
Drive1_Change
FormLoading = False
End Sub
Private Sub GetDirContents(sPath As String)
Dim oNode As Node
Dim sTemp As String
Dim sMatch As String
If tvwDirectory.Nodes(sPath). Children > 0 Then Exit Sub
If Right$(sPath, 1) = "\" Then
sTemp = sPath
Else
sTemp = sPath & "\"
End If
sMatch = Dir$(sTemp & "\*.", vbDirectory)
Do While sMatch <> ""
If sMatch <> "." And sMatch <> ".." Then
If ((GetAttr(sTemp & sMatch) And vbDirectory) = vbDirectory) Then
Set Node = tvwDirectory.Nodes.Add(sPa th, tvwChild, sTemp & sMatch, sMatch, 2)
End If
End If
sMatch = Dir$()
Loop
End Sub
Private Sub tvwDirectory_Collapse(ByVa l Node As MSComctlLib.Node)
Node.Image = 2
End Sub
Private Sub tvwDirectory_Expand(ByVal Node As MSComctlLib.Node)
Dim oNode As Node
Dim vIndex As Variant
Node.Image = 3
GetDirContents Node.Key
If Node.Children > 0 Then
Set oNode = Node.Child
' GetDirContents oNode.Key
If Not oNode.LastSibling Is Nothing Then
vIndex = oNode.LastSibling.Index
Do While Not oNode Is Nothing
GetDirContents oNode.Key
If oNode.Index <> vIndex Then
Set oNode = oNode.Next
Else
Set oNode = Nothing
End If
Loop
End If
End If
End Sub
Private Sub tvwDirectory_NodeClick(ByV al Node As MSComctlLib.Node)
Dim oNode As Node
Dim oListItem As ListItem
Dim vIndex As Variant
Dim dblDirSize As Double
Dim dblTemp As Double
lvwDisplay.ListItems.Clear
GetDirContents Node.Key
Set oListItem = lvwDisplay.ListItems.Add(, , "Files", 4, 4)
' dblDirSize = GetDirectorySize(Node.Key)
oListItem.SubItems(1) = Format((dblDirSize + 1) / 1000, "###,###,###,##0") & "KB"
oListItem.SubItems(2) = "*****"
If Node.Children > 0 Then
Set oNode = Node.Child
' GetDirContents oNode.Key
If Not oNode.LastSibling Is Nothing Then
vIndex = oNode.LastSibling.Index
Do While Not oNode Is Nothing
GetDirContents oNode.Key
Set oListItem = lvwDisplay.ListItems.Add(, , oNode.Text, 2, 2)
dblDirSize = GetDirectorySize(oNode.Key )
oListItem.SubItems(1) = Format((dblDirSize + 1) / 1000, "###,###,###,##0") & "KB"
oListItem.SubItems(2) = "*****"
If oNode.Index <> vIndex Then
Set oNode = oNode.Next
Else
Set oNode = Nothing
End If
Loop
End If
End If
dblDirSize = 0
For i = 1 To lvwDisplay.ListItems.Count
Set oListItem = lvwDisplay.ListItems(i)
dblDirSize = dblDirSize + CDbl(Left(oListItem.SubIte ms(1), Len(oListItem.SubItems(1)) - 2))
Next i
For i = 1 To lvwDisplay.ListItems.Count
Set oListItem = lvwDisplay.ListItems(i)
dblTemp = CDbl(Left(oListItem.SubIte ms(1), Len(oListItem.SubItems(1)) - 2))
If dblTemp > 0 Then
oListItem.SubItems(2) = String(((dblTemp / dblDirSize) * 100), "*")
End If
Next i
End Sub
I finally settled on loading one level at a time. So, first load all of the top level folders. Then, as you expand a folder just get it's direct child folders etc.
My example was also trying to track the folder sizes to help me locate disk-hogs. Here is some of the code. If you want the stuff that actually gets the directory size let me know. With a little tinkering this should do what you want.
Open a projet with a Treeview, a ListView, a Drive File List, name them appropriatly and paste in this code. You might have to comment out the calls to GetDirectorySize.
Private Sub Drive1_Change()
Dim oNode As Node
tvwDirectory.Nodes.Clear
Set Node = tvwDirectory.Nodes.Add(, , Left$(Drive1.Drive, 1) & ":", Left$(Drive1.Drive, 1) & ":", 1)
GetDirContents Left$(Drive1.Drive, 1) & ":"
tvwDirectory_NodeClick tvwDirectory.Nodes(1)
tvwDirectory.Nodes(1).Expa
End Sub
Private Sub Form_Load()
FormLoading = True
lvwDisplay.View = lvwReport
lvwDisplay.ColumnHeaders.A
lvwDisplay.ColumnHeaders.A
lvwDisplay.ColumnHeaders.A
Drive1.Drive = "C:"
Drive1_Change
FormLoading = False
End Sub
Private Sub GetDirContents(sPath As String)
Dim oNode As Node
Dim sTemp As String
Dim sMatch As String
If tvwDirectory.Nodes(sPath).
If Right$(sPath, 1) = "\" Then
sTemp = sPath
Else
sTemp = sPath & "\"
End If
sMatch = Dir$(sTemp & "\*.", vbDirectory)
Do While sMatch <> ""
If sMatch <> "." And sMatch <> ".." Then
If ((GetAttr(sTemp & sMatch) And vbDirectory) = vbDirectory) Then
Set Node = tvwDirectory.Nodes.Add(sPa
End If
End If
sMatch = Dir$()
Loop
End Sub
Private Sub tvwDirectory_Collapse(ByVa
Node.Image = 2
End Sub
Private Sub tvwDirectory_Expand(ByVal Node As MSComctlLib.Node)
Dim oNode As Node
Dim vIndex As Variant
Node.Image = 3
GetDirContents Node.Key
If Node.Children > 0 Then
Set oNode = Node.Child
' GetDirContents oNode.Key
If Not oNode.LastSibling Is Nothing Then
vIndex = oNode.LastSibling.Index
Do While Not oNode Is Nothing
GetDirContents oNode.Key
If oNode.Index <> vIndex Then
Set oNode = oNode.Next
Else
Set oNode = Nothing
End If
Loop
End If
End If
End Sub
Private Sub tvwDirectory_NodeClick(ByV
Dim oNode As Node
Dim oListItem As ListItem
Dim vIndex As Variant
Dim dblDirSize As Double
Dim dblTemp As Double
lvwDisplay.ListItems.Clear
GetDirContents Node.Key
Set oListItem = lvwDisplay.ListItems.Add(,
' dblDirSize = GetDirectorySize(Node.Key)
oListItem.SubItems(1) = Format((dblDirSize + 1) / 1000, "###,###,###,##0") & "KB"
oListItem.SubItems(2) = "*****"
If Node.Children > 0 Then
Set oNode = Node.Child
' GetDirContents oNode.Key
If Not oNode.LastSibling Is Nothing Then
vIndex = oNode.LastSibling.Index
Do While Not oNode Is Nothing
GetDirContents oNode.Key
Set oListItem = lvwDisplay.ListItems.Add(,
dblDirSize = GetDirectorySize(oNode.Key
oListItem.SubItems(1) = Format((dblDirSize + 1) / 1000, "###,###,###,##0") & "KB"
oListItem.SubItems(2) = "*****"
If oNode.Index <> vIndex Then
Set oNode = oNode.Next
Else
Set oNode = Nothing
End If
Loop
End If
End If
dblDirSize = 0
For i = 1 To lvwDisplay.ListItems.Count
Set oListItem = lvwDisplay.ListItems(i)
dblDirSize = dblDirSize + CDbl(Left(oListItem.SubIte
Next i
For i = 1 To lvwDisplay.ListItems.Count
Set oListItem = lvwDisplay.ListItems(i)
dblTemp = CDbl(Left(oListItem.SubIte
If dblTemp > 0 Then
oListItem.SubItems(2) = String(((dblTemp / dblDirSize) * 100), "*")
End If
Next i
End Sub
ASKER
hi all,
actually, this one works for me:
code provided by ameba:
************************** ********** **
To load a tree, I suggest Chris Eastwood's code, which first adds all nodes to root, and later reparents
them. .Tag property is used to cache ParentID.
Private Sub FillTree()
Dim lCount As Long
Dim rsSections As Recordset
Dim sParent As String
Dim sKey As String
Dim sText As String
Dim bBookMark As Boolean
Dim nNode As Node
On Error GoTo vbErrorHandler
'
' Populate our TreeView Control with the Data from our database
'
Set rsSections = mDB.OpenRecordset("select * from codeitems order by parentid")
Set tvCodeItems.ImageList = Nothing
Set tvCodeItems.ImageList = ImageList1
If rsSections.BOF And rsSections.EOF Then
tvCodeItems.Nodes.Add , , "ROOT", "Code Library", "VIEWBOOKMARKS"
BoldTreeNode tvCodeItems.Nodes("ROOT")
Exit Sub
End If
TreeRedraw tvCodeItems.hwnd, False
rsSections.MoveFirst
Set tvCodeItems.ImageList = Nothing
Set tvCodeItems.ImageList = ImageList1
'
' Populate the TreeView Nodes
'
With tvCodeItems.Nodes
.Clear
.Add , , "ROOT", "Code Library", "VIEWBOOKMARKS"
'
' Make our Root Item BOLD
'
BoldTreeNode tvCodeItems.Nodes("ROOT")
'
' Now add all nodes into TreeView, but under the root item.
' We reparent the nodes in the next step
'
Do Until rsSections.EOF
sParent = rsSections("ParentID").Val ue
sKey = rsSections("ID").Value
sText = rsSections("Description"). Value
Set nNode = .Add("ROOT", tvwChild, "C" & sKey, sText, "FOLDER")
'
' Record parent ID
'
nNode.Tag = "C" & sParent
rsSections.MoveNext
Loop
End With
'
' Here's where we rebuild the structure of the nodes
'
For Each nNode In tvCodeItems.Nodes
sParent = nNode.Tag
If Len(sParent) > 0 Then ' Don't try and reparent the ROOT !
If sParent = "C0" Then
sParent = "ROOT"
End If
Set nNode.Parent = tvCodeItems.Nodes(sParent)
End If
Next
'
' Now setup the images for each node in the treeview & set each node to
' be sorted if it has children
'
For Each nNode In tvCodeItems.Nodes
If nNode.Children = 0 Then
nNode.Image = "CHILD"
Else
nNode.Sorted = True
End If
Next
Set rsSections = Nothing
'
' Expand the Root Node
'
tvCodeItems.Nodes("ROOT"). Sorted = True
tvCodeItems.Nodes("ROOT"). Expanded = True
TreeRedraw tvCodeItems.hwnd, True
Exit Sub
vbErrorHandler:
TreeRedraw tvCodeItems.hwnd, True
MsgBox Err.Number & " " & Err.Description & " " & Err.Source
End Sub
Private Sub TreeRedraw(ByVal lHwnd As Long, ByVal bRedraw As Boolean)
SendMessageLong lHwnd, WM_SETREDRAW, bRedraw, 0
End Sub
************************
all agree that this solves it for me? (i agree, b/c it did exactly what i wanted...)
actually, this one works for me:
code provided by ameba:
**************************
To load a tree, I suggest Chris Eastwood's code, which first adds all nodes to root, and later reparents
them. .Tag property is used to cache ParentID.
Private Sub FillTree()
Dim lCount As Long
Dim rsSections As Recordset
Dim sParent As String
Dim sKey As String
Dim sText As String
Dim bBookMark As Boolean
Dim nNode As Node
On Error GoTo vbErrorHandler
'
' Populate our TreeView Control with the Data from our database
'
Set rsSections = mDB.OpenRecordset("select * from codeitems order by parentid")
Set tvCodeItems.ImageList = Nothing
Set tvCodeItems.ImageList = ImageList1
If rsSections.BOF And rsSections.EOF Then
tvCodeItems.Nodes.Add , , "ROOT", "Code Library", "VIEWBOOKMARKS"
BoldTreeNode tvCodeItems.Nodes("ROOT")
Exit Sub
End If
TreeRedraw tvCodeItems.hwnd, False
rsSections.MoveFirst
Set tvCodeItems.ImageList = Nothing
Set tvCodeItems.ImageList = ImageList1
'
' Populate the TreeView Nodes
'
With tvCodeItems.Nodes
.Clear
.Add , , "ROOT", "Code Library", "VIEWBOOKMARKS"
'
' Make our Root Item BOLD
'
BoldTreeNode tvCodeItems.Nodes("ROOT")
'
' Now add all nodes into TreeView, but under the root item.
' We reparent the nodes in the next step
'
Do Until rsSections.EOF
sParent = rsSections("ParentID").Val
sKey = rsSections("ID").Value
sText = rsSections("Description").
Set nNode = .Add("ROOT", tvwChild, "C" & sKey, sText, "FOLDER")
'
' Record parent ID
'
nNode.Tag = "C" & sParent
rsSections.MoveNext
Loop
End With
'
' Here's where we rebuild the structure of the nodes
'
For Each nNode In tvCodeItems.Nodes
sParent = nNode.Tag
If Len(sParent) > 0 Then ' Don't try and reparent the ROOT !
If sParent = "C0" Then
sParent = "ROOT"
End If
Set nNode.Parent = tvCodeItems.Nodes(sParent)
End If
Next
'
' Now setup the images for each node in the treeview & set each node to
' be sorted if it has children
'
For Each nNode In tvCodeItems.Nodes
If nNode.Children = 0 Then
nNode.Image = "CHILD"
Else
nNode.Sorted = True
End If
Next
Set rsSections = Nothing
'
' Expand the Root Node
'
tvCodeItems.Nodes("ROOT").
tvCodeItems.Nodes("ROOT").
TreeRedraw tvCodeItems.hwnd, True
Exit Sub
vbErrorHandler:
TreeRedraw tvCodeItems.hwnd, True
MsgBox Err.Number & " " & Err.Description & " " & Err.Source
End Sub
Private Sub TreeRedraw(ByVal lHwnd As Long, ByVal bRedraw As Boolean)
SendMessageLong lHwnd, WM_SETREDRAW, bRedraw, 0
End Sub
************************
all agree that this solves it for me? (i agree, b/c it did exactly what i wanted...)
ameba, I hadn't heard of this technique before. Is it faster to load this way? Or does is just simplify retrieving the data so that you don't have to order the recordset with all children following their parents.
Paurths,
What advantage is there to recreate the function/contents of the DirectoryList box? Messing with a Treeview control is slower and performs unnecessary to iterate/add-node for a directory the user isn't interested in seeing.
What advantage is there to recreate the function/contents of the DirectoryList box? Messing with a Treeview control is slower and performs unnecessary to iterate/add-node for a directory the user isn't interested in seeing.
ASKER
that is correct aikimark,
but there wont be no users using this program.
its for my use only.
comment of Date: 03/06/2002 03:47PM PST
************************** **
What i would like to do is:
if i could fill a treeview with all the folders, click on a node (e.g. a folder on a shared folder)
immediatly know what groups, users, have what permissions.
I know i can retrieve this information in my form where the folders are shown/added.
I was just wondering if it can be done. (i would probably be the only person on this planet using this
program, but i figured it would be good excercice...)
************************** ***
since the database will hold all the users, global groups, local groups, folders, permissions on folders it would / could give me a quick view 'who can do what' when i click a folder.
Sometimes when i receive a call from any user of our network asking me why on earth (s)he can not write/delete/access a certain folder i need to look up permissions. The way it is done now takes too long.
with a click on folder in the treeview i want to see why this user calls me.
In the end there wont be that many folders in this database.
Only the folders where the shared data is, will be present. (for several servers tho) So i'm not talking about a couple of thousand folders. (perhaps in the future)
Since the security only goes 3 or 4 levels deep, this must be managable.
If a user adds a folder at level e.g. 7 just for her/his sake i dont need that in the database. (for now)
like i said, there might be programs out there that have a solution for this, but i really want a total program where i can also place computers on desks. (using Visio for the graphical interface of the building / offices --> is build automatically on the click of a button, nice tool, when a desk gets moved i give it other co-ordinates in the program and it will show up at the correct place in the graphical overview --> once it is finished that is!)
connect computers to outlets, the outlets to the swichtes,
desks have several outlets at their disposal, so u can connect computers to a desk/outlet, printers and printservers.
there are several other issues in it, but i cant name them all or i'll fill at least 3 pages here...
It is big...
cheers
Ricky
but there wont be no users using this program.
its for my use only.
comment of Date: 03/06/2002 03:47PM PST
**************************
What i would like to do is:
if i could fill a treeview with all the folders, click on a node (e.g. a folder on a shared folder)
immediatly know what groups, users, have what permissions.
I know i can retrieve this information in my form where the folders are shown/added.
I was just wondering if it can be done. (i would probably be the only person on this planet using this
program, but i figured it would be good excercice...)
**************************
since the database will hold all the users, global groups, local groups, folders, permissions on folders it would / could give me a quick view 'who can do what' when i click a folder.
Sometimes when i receive a call from any user of our network asking me why on earth (s)he can not write/delete/access a certain folder i need to look up permissions. The way it is done now takes too long.
with a click on folder in the treeview i want to see why this user calls me.
In the end there wont be that many folders in this database.
Only the folders where the shared data is, will be present. (for several servers tho) So i'm not talking about a couple of thousand folders. (perhaps in the future)
Since the security only goes 3 or 4 levels deep, this must be managable.
If a user adds a folder at level e.g. 7 just for her/his sake i dont need that in the database. (for now)
like i said, there might be programs out there that have a solution for this, but i really want a total program where i can also place computers on desks. (using Visio for the graphical interface of the building / offices --> is build automatically on the click of a button, nice tool, when a desk gets moved i give it other co-ordinates in the program and it will show up at the correct place in the graphical overview --> once it is finished that is!)
connect computers to outlets, the outlets to the swichtes,
desks have several outlets at their disposal, so u can connect computers to a desk/outlet, printers and printservers.
there are several other issues in it, but i cant name them all or i'll fill at least 3 pages here...
It is big...
cheers
Ricky
ameba,
I tried the code above but the declaration for the API SendMessageLong is missing. I tried pasting SendMessage from the API text viewer, re-aliasing it to SendMessageLong. I also set the lParam value to ByVal as this sometimes causes problems if it's passed ByRef, but still the call is appearantly failing.
What happens is that the tree keeps trying to redraw, and this makes the process incredibly slow. The SendMessageLong returns a zero, so, it looks like it works...
I tried every combination I could think of for SendMessage and still no luck. Finally, I found an alternative API for LockWindowUpdate. This worked perfectly.
'Private Declare Function SendMessageLong Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
'Private Const WM_SETREDRAW = &HB
Private Declare Function LockWindowUpdate Lib "user32" (ByVal hwndLock As Long) As Long
Private Sub TreeRedraw(ByVal lHwnd As Long, ByVal bRedraw As Boolean)
' SendMessageLong lHwnd, WM_SETREDRAW, bRedraw, 0
' SendMessageLong lHwnd, WM_SETREDRAW, bRedraw, &O0
' SendMessageLong lHwnd, WM_SETREDRAW, bRedraw, 0&
' SendMessageLong lHwnd, WM_SETREDRAW, bRedraw, ByVal 0&
' SendMessageLong lHwnd, WM_SETREDRAW, -CLng(bRedraw), 0&
' SendMessageLong lHwnd, WM_SETREDRAW, Abs(CLng(bRedraw)), 0&
If bRedraw Then
LockWindowUpdate 0
Else
LockWindowUpdate lHwnd
End If
End Sub
I tried the code above but the declaration for the API SendMessageLong is missing. I tried pasting SendMessage from the API text viewer, re-aliasing it to SendMessageLong. I also set the lParam value to ByVal as this sometimes causes problems if it's passed ByRef, but still the call is appearantly failing.
What happens is that the tree keeps trying to redraw, and this makes the process incredibly slow. The SendMessageLong returns a zero, so, it looks like it works...
I tried every combination I could think of for SendMessage and still no luck. Finally, I found an alternative API for LockWindowUpdate. This worked perfectly.
'Private Declare Function SendMessageLong Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
'Private Const WM_SETREDRAW = &HB
Private Declare Function LockWindowUpdate Lib "user32" (ByVal hwndLock As Long) As Long
Private Sub TreeRedraw(ByVal lHwnd As Long, ByVal bRedraw As Boolean)
' SendMessageLong lHwnd, WM_SETREDRAW, bRedraw, 0
' SendMessageLong lHwnd, WM_SETREDRAW, bRedraw, &O0
' SendMessageLong lHwnd, WM_SETREDRAW, bRedraw, 0&
' SendMessageLong lHwnd, WM_SETREDRAW, bRedraw, ByVal 0&
' SendMessageLong lHwnd, WM_SETREDRAW, -CLng(bRedraw), 0&
' SendMessageLong lHwnd, WM_SETREDRAW, Abs(CLng(bRedraw)), 0&
If bRedraw Then
LockWindowUpdate 0
Else
LockWindowUpdate lHwnd
End If
End Sub
ASKER
there is more,
'BoldTreeNode tvCodeItems.Nodes("ROOT")
is replaced by (b/c VB6)
tvCodeItems.Nodes("ROOT"). Bold = True
'BoldTreeNode tvCodeItems.Nodes("ROOT")
is replaced by (b/c VB6)
tvCodeItems.Nodes("ROOT").
ASKER
i guess its time to close this one.
any suggestions?
cheers
Ricky
any suggestions?
cheers
Ricky
Despite the slight omissions in the code, I think ameba's answer fits your needs. It also taught me a new and valuable trick. I've often gone to great lengths to try to order my rows in a hierarchical self-referencing table in order to add them to the tree in the proper order, and now I know that I can add them in any order and then re-parent them. It's orders of magnitude faster than whatever I've done before.... so, it's a technique well worth the points.
ASKER
have already given ameba the points for his solution on 03/07/2002.
https://www.experts-exchange.com/jsp/qManageQuestion.jsp?ta=visualbasic&qid=20274655
cheers
Ricky
https://www.experts-exchange.com/jsp/qManageQuestion.jsp?ta=visualbasic&qid=20274655
cheers
Ricky
Paurths,
What are you going to do with THIS question?
Please close this question if we've answered it. If you have questions, please consult the Community Support TA and ask them what you should do.
What are you going to do with THIS question?
Please close this question if we've answered it. If you have questions, please consult the Community Support TA and ask them what you should do.
Paurths,
It's important to award the point to the expert inside of the question. Because then the question gets saved to the Previously Asked Questions area and someone else will eventually "buy" the question and get the benefit of the excellent advice you've received here. If you award the points in some other question without the technical stuff, then this question ends up deleted and then all of the good advice gets lost for others.......
It's important to award the point to the expert inside of the question. Because then the question gets saved to the Previously Asked Questions area and someone else will eventually "buy" the question and get the benefit of the excellent advice you've received here. If you award the points in some other question without the technical stuff, then this question ends up deleted and then all of the good advice gets lost for others.......
ASKER
please see : https://www.experts-exchange.com/jsp/qManageQuestion.jsp?ta=commspt&qid=20277808
all ok ?
cheers
Ricky
all ok ?
cheers
Ricky
Did you leave someone out?
If not, you will probably need to lower your points from 200 to 150 to be evenly divisible into three 50-point slices.
If not, you will probably need to lower your points from 200 to 150 to be evenly divisible into three 50-point slices.
Points refunded and reduced to 50 for a point split. Now you can accept an experts comment as an answer and make questions in this topic area for the other experts.
Computer101
E-E Moderator
Computer101
E-E Moderator
ASKER
mdougan please see ; https://www.experts-exchange.com/jsp/qManageQuestion.jsp?ta=visualbasic&qid=20277879
matthewroberts please see ; https://www.experts-exchange.com/jsp/qManageQuestion.jsp?ta=visualbasic&qid=20277878
cheers
Ricky
matthewroberts please see ; https://www.experts-exchange.com/jsp/qManageQuestion.jsp?ta=visualbasic&qid=20277878
cheers
Ricky
Oh, sorry, I didn't participate in this thread.
- the function I suggested in another thread is not recursive, so I didn't want to jump in here.
The sample is somewhere on codeguru, but I don't have the exact link, and it works only for version 5 of the Common Controls.
mdougan,
> I tried the code above but the declaration for the API SendMessageLong is missing
You have the right version of SendMessageLong, but it is possible it doesn't work with version 6 of the TreeView.
LockWindowUpdate can work OK in most cases. Or if there are not too many items, "tv.Visible = False" can work.
I don't use Treeview often, but for Listview, I got best results when sending WM_SETREDRAW message to PARENT FORM:
' from caList class
Public Property Let Redraw(ByVal Redraw As Boolean)
Dim rc As RECT, ret As Long
If Redraw Then
Call SendMessage(ListView.Paren t.hwnd, WM_SETREDRAW, REDRAWON, 0&)
' this is a bit less flicker
ret = GetClientRect(ListView.hwn d, rc)
ret = InvalidateRect(ListView.hw nd, rc, 0&)
Else
Call SendMessage(ListView.Paren t.hwnd, WM_SETREDRAW, REDRAWOFF, 0&)
End If
End Property
- the function I suggested in another thread is not recursive, so I didn't want to jump in here.
The sample is somewhere on codeguru, but I don't have the exact link, and it works only for version 5 of the Common Controls.
mdougan,
> I tried the code above but the declaration for the API SendMessageLong is missing
You have the right version of SendMessageLong, but it is possible it doesn't work with version 6 of the TreeView.
LockWindowUpdate can work OK in most cases. Or if there are not too many items, "tv.Visible = False" can work.
I don't use Treeview often, but for Listview, I got best results when sending WM_SETREDRAW message to PARENT FORM:
' from caList class
Public Property Let Redraw(ByVal Redraw As Boolean)
Dim rc As RECT, ret As Long
If Redraw Then
Call SendMessage(ListView.Paren
' this is a bit less flicker
ret = GetClientRect(ListView.hwn
ret = InvalidateRect(ListView.hw
Else
Call SendMessage(ListView.Paren
End If
End Property
Are you looking for alternatives?
Is your problem mostly a processing problem?
Performance problem?
Directory name/parentage data gathering problem?
I assume you need to support cascading security, group security, as well as user-specific security. If I'm wrong, please let me know.
What are the details of this application?