Filter Results

The place for threads about version 1.x of TimoSoft ExplorerTreeView.
aka
Lieutenant
Posts: 17
Joined: 05 Jan 2006, 12:27

Filter Results

Post by aka »

Hi Timo,

I am still an enthusiastic user of ExplorerTreeView #1 and would be very thankful, if you could help me along with the following problem:
How can I create an array of those items, which correspond to the settings of the file and/or folder filters? After searching in the forums and several successless trials with "Explorer_BeforeInsertItem" and "Explorer_ItemLoadingSubItems" , I don't have any idea how to get this array of indexes or even better the complete path names.

Hoping you will help me once again I thank you in advance.
Best regards
aka
User avatar
TiKu
Administrator
Administrator
Posts: 832
Joined: 28 Sep 2004, 21:10
Location: München
Contact:

Re: Filter Results

Post by TiKu »

I'm not sure I understand you correctly. You've set the FileFilters and FolderFilters properties to some filter string and activated UseFileFilters and UseFolderFilters, so that the items displayed by the control are filtered correctly? Am I right so far?
Which items do you want to store in an array now? Those which are displayed?
Crunching for Fab36_Folding-Division at Folding@Home. Join Fab36/Fab30! - Folding@Home and BOINC
Boycott DRM! Boycott HDCP!
aka
Lieutenant
Posts: 17
Joined: 05 Jan 2006, 12:27

Re: Filter Results

Post by aka »

Hi Timo,

sorry for my not understandable question. I try it once again using an expample:

Setting the folder filter to "P*|Tools*" and the file filter to "*.exe" lets ExplorerTreeView
display all folders whose name starts with "P" and their subfolders whose name starts with "Tools". All displayed files have the "*.exe"-extension. So -to answer your question- the filters work well (of course "Use...Filter" is set to "True"). Now I would like to get a handle to each folder and/or file (not always both filters are used together) ETV is showing for the specified filter(s). Storing this handle in an array, collection or listbox would it make easy to jump by code to the next or previous filter result for example. To illustrate the usefullness of such a code, please imagine the following configuration:
Folders are not filtered, but the file filter is set to "*.exe" for all storage devices of the PC. In my case the filter result list is several 10.000's long and additionally all folders are shown, if all or even one logical drive is expanded by code. Having a command button by which one can jump to the next/previous filter result with or without for example skipping 50 filter results, will make it very easy to view the result of filtering or to export it or whatever your fantasy requires.

So the answer to your last question is: I want to store ALL FILTER RESULTS, indenpendend of their visibilty.

Best regards
aka
User avatar
TiKu
Administrator
Administrator
Posts: 832
Joined: 28 Sep 2004, 21:10
Location: München
Contact:

Re: Filter Results

Post by TiKu »

It won't work this way, for two reasons.
1) The control loads data on demand (when the user expands an item for the first time) and may also decide to remove data that is located in a currently collapsed sub tree. Therefore the best you could get is a list of all items that match the filters and are currently visible (it's okay if the user would have to scroll to make the items really visible).
2) The control updates itself on shell events like file creation, file deletion, file renaming, file moving and so on. Your list would get out of sync rather soon. Also the item handles may change, because the control sometimes removes an item and re-adds it. This has to do with the way how Windows notifies programs about shell events.

However, to create such a list of items that match the filters, you just need to iterate over all items using ItemGetNextItem and ItemGetFirstSubItem. For each item, check whether it's part of the file system using ItemIsPartOfFileSystem. If it's part of the file system, then the filters have been applied and the item obviously matches them (because otherwise it wouldn't be in the control).

Due to the problems described initially, it'd be better to search for the next item that matches the filters not before the user really clicks the button instead of storing the item handles of all matching items in a lookup table.
Crunching for Fab36_Folding-Division at Folding@Home. Join Fab36/Fab30! - Folding@Home and BOINC
Boycott DRM! Boycott HDCP!
aka
Lieutenant
Posts: 17
Joined: 05 Jan 2006, 12:27

Re: Filter Results

Post by aka »

Hi Tiku,

thanks a lot for your reply.
I understand your argumentation and have changed the code of the application correspondingly. Unfortunatly I failed completely, when trying to identify the filter results by iterating as supposed by you. The sub...

Code: Select all

Public Sub Next_Filter_Result(ByVal Parent_Item As Long)
    
   Dim Next_Item As Long
   Dim Sub_Item As Long
    
   ' Jump to Next Item Matching Folder/File Settings
   With ETV
      Next_Item = .ItemGetNextItem(Parent_Item)
      If .ItemIsPartOfFileSystem(Next_Item) Then
         .SelectedItem = Next_Item
         .ItemEnsureVisible (.SelectedItem)
         Exit Sub
      Else
         Sub_Item = .ItemGetFirstSubItem(Next_Item)
         Do While Sub_Item <> -1
            If .ItemIsPartOfFileSystem(Sub_Item) Then
               .SelectedItem = Sub_Item
               .ItemEnsureVisible (.SelectedItem)
               Exit Do
            End If
            Sub_Item = .ItemGetNextItem(Sub_Item)
         Loop
   End With
       
End Sub
... either "Debug.Print"s (deleted in the code above) the next logical drive or nothing. I don't want to be impudent, but if you happen to have a code snippet suitable as starting point, I would be very thankful.

In any case
I thank you for your help so fare and wish you all the best
aka
User avatar
TiKu
Administrator
Administrator
Posts: 832
Joined: 28 Sep 2004, 21:10
Location: München
Contact:

Re: Filter Results

Post by TiKu »

Let's assume the tree contains these items:

Code: Select all

Parent 1
  |- Child 1
      |- Grandchild 1
      |- Grandchild 2
  |- Child 2
  |- Child 3
  |- Child 4
Parent 2
"Child 1" and "Grandchild 1" don't match the filters, all other items do match them. "Parent 1" is currently selected.

The user clicks the button. Do you want "Grandchild 2" to become selected or "Child 2"? I'll assume "Grandchild 2", so the code should look like this:

Code: Select all

Public Function Next_Filter_Result(ByVal hSelection As Long) As Boolean
  Dim hNext As Long

  With ETV
    hNext = .ItemGetFirstSubItem(hSelection)
    If hNext = 0 Then
      hNext = .ItemGetNextItem(hSelection)
    End If
    Do While hNext <> 0
      If .ItemIsPartOfFileSystem(hNext) Then
        .SelectedItem = hNext
        .ItemEnsureVisible hNext
        Next_Filter_Result = True
        Exit Function
      End If
      If Next_Filter_Result(hNext) Then
        Next_Filter_Result = True
        Exit Function
      End If
      hNext = .ItemGetNextItem(hNext)
    Loop
  End With
End Function
The code does a depth search.
aka wrote:I thank you for your help so fare and wish you all the best
Thanks, same to you.
Crunching for Fab36_Folding-Division at Folding@Home. Join Fab36/Fab30! - Folding@Home and BOINC
Boycott DRM! Boycott HDCP!
aka
Lieutenant
Posts: 17
Joined: 05 Jan 2006, 12:27

Re: Filter Results

Post by aka »

Hi Tiku,

thank you very, very much for the posted code. Unfortunately I don't get it working correct.
For the first trials I used for reasons of simplicity a single file filter like "*.psd". To the application I am working on I added a command button:

Private Sub Command1_Click()
Do
DoEvents
Loop Until Next_Filter_Result (ETV.SelectedItem)
End Sub

I expected by clicking Command1, to see the next file, matching the filter specifications, because the requirements for this are implemented in your Function
"Next_Filter_Result(hSelection)", even expanding folders and scrolling down.

But what happens is:
After selecting an arbitrary item in the tree, a click on the command button causes the next visible item to be selected, no matter if it itself or the folder and subfolders content files matching the filter specification. A second click on the button causes an "Out of stack space"-error (run-time errror 28) and the application is terminated if running in the IDE.

Error 28 is raised by the first line of the recursion in your function (signed by me with "**"):

** If Next_Filter_Result(hNext) Then **
Next_Filter_Result = True
Exit Function
End If


As ExplorerTreeView is applying the filter settings to 100% correctly and you are a professional coder, there must be something wrong with my loop. And I don't have any other idea on how to use the function.

Are you willing to help me again or did I stress your nerves over the limit?

In any case I wish you all the best and like to say a warm and honest THANK's A LOT for this great component. I did not count it, but I guess in the meantime it is the one or one of the core parts in most of my hobbyist-programs.

aka
User avatar
TiKu
Administrator
Administrator
Posts: 832
Joined: 28 Sep 2004, 21:10
Location: München
Contact:

Re: Filter Results

Post by TiKu »

Sorry, my fault. I did not test the code.

Code: Select all

If hNext = 0 Then
must be

Code: Select all

If hNext = -1 Then
and

Code: Select all

Do While hNext <> 0
must be

Code: Select all

Do While hNext <> -1
Crunching for Fab36_Folding-Division at Folding@Home. Join Fab36/Fab30! - Folding@Home and BOINC
Boycott DRM! Boycott HDCP!
aka
Lieutenant
Posts: 17
Joined: 05 Jan 2006, 12:27

Re: Filter Results

Post by aka »

Hi Tiku,

I am really thankful for the corrections you posted. Unfortunately they brought only a small improvement: the stack overflow is avoided. All the other issues remain unchanged. Invoking the function "Next_Filter_Result" with a "Do....Until" loop as explained in the last post does nothing else than selecting the next tree item.
I think this whole matter is to complicated for me and still assume, that my
approach with this loop is wrong. So I have to give up, if you don't have the wish to continue working on the problem. What a pity!

Best regards and -even if I repeat myself- thanks a lot for your efforts
aka
User avatar
TiKu
Administrator
Administrator
Posts: 832
Joined: 28 Sep 2004, 21:10
Location: München
Contact:

Re: Filter Results

Post by TiKu »

Maybe I'm still understanding wrong what you're trying to achieve. Sometimes I'm a bit slow off the mark. :)

Could you please create a small sample project, that creates some files and folders and also has ExplorerTreeView and the CommandButton that triggers Next_Filter_Result integrated? With such a sample it should be easier to explain the expected behavior. You could explain it like this:
  • Select folder/file abc
  • Click the "Next result" button. Expected behavior: Folder/file def gets selected. Observed behavior: Folder/file xyz gets selected.
and so on.
Crunching for Fab36_Folding-Division at Folding@Home. Join Fab36/Fab30! - Folding@Home and BOINC
Boycott DRM! Boycott HDCP!
aka
Lieutenant
Posts: 17
Joined: 05 Jan 2006, 12:27

Re: Filter Results

Post by aka »

Hi TiKu,

you can not imagine how happy and thankful I am about your last post.

As I don't like to create files and folders on your PC, I attached an archive "TimoSoft.zip" with some folders, subfolders and txt-files. You can store them were it is suitable for you. The demo project is zipped to "Demo.zip". It uses only a single file filter (*.txt)

The demo behaves as follows:

Selecting the "main" folder "TimoSoft" expands this folder and 2 subfolders and 2 files become visible.

After a click on "Jump to Next Filter Result" the first subfolder "TimoSoft Sub1" is selected, but not expanded as intended, altough it contains txt-files in its root and a further subfolder. Further clicks select "TimoSoft Sub2" -> "timo1.txt" -> "timo2.txt". Now you are at the last item of this folder and further click leads to a hung-up.

The summary of current state is very easy: the code always selects the next tree item without changing the level and regardless of the filter settings. If a movement a level up is required, the program does not respond anymore.

What I try to reach is:
Selecting an arbitrary item in the tree and clicking "Jump to Next Filter Result" should find the next filter result (a file OR a folder) independent of the depth of its location, expand all its parent folders, make it visible and select it. The next click should do the same, even if due to the deep level of the last selection, the code needs to jump up several tree levels and/or needs to change the logical drive.

If I have an algorithm for this, I intent to modify this that way, that it works in the other direction.

With your help, I could realize all features I wanted to have in my ExplorerTreeView-programs up to now. But this matter seems to be fare over my skills.

Best regards
aka
TimoSoft.zip
(4.72 KiB) Downloaded 560 times
Demo.zip
(2.73 KiB) Downloaded 591 times
User avatar
TiKu
Administrator
Administrator
Posts: 832
Joined: 28 Sep 2004, 21:10
Location: München
Contact:

Re: Filter Results

Post by TiKu »

aka wrote:After a click on "Jump to Next Filter Result" the first subfolder "TimoSoft Sub1" is selected, but not expanded as intended, altough it contains txt-files in its root and a further subfolder.
That's normal. The contents of "TimoSoft Sub1" won't be loaded until this item is expanded. The code that searches for the next result, of course checks only those files and folders that have been loaded into the control. Call ItemLoadSubItems to make sure the sub-items are loaded.

Here's the code that will call ItemLoadSubItems and search upwards if it reaches the end of a sub-tree.

Code: Select all

Private Sub Next_Filter_Result(ByVal hSelection As Long)
  Dim hNext As Long
  Dim l As Long

  With ETV
    hNext = FindNextMatchInSubTree(hSelection)
    If hNext = -1 Then
      ' try parent item's next sibling sub-tree
      hNext = hSelection
      Do
        hNext = .ItemGetParentItem(hNext)
        If hNext = 0 Then hNext = -1     ' special handling for ShowRoot = False
        If hNext <> -1 Then hNext = .ItemGetNextItem(hNext)
        If hNext = -1 Then
          ' we've reached the end of the tree
          Exit Do
        ElseIf ItemMatchesFilters(hNext) Then
          ' we've found a match
          Exit Do
        Else
          l = FindNextMatchInSubTree(hNext)
          If l <> -1 Then
            ' we've found a match
            hNext = l
            Exit Do
          End If
        End If
      Loop
    End If

    If hNext <> -1 Then
      ' we've found a result
      .SelectedItem = hNext
      .ItemEnsureVisible hNext
    End If
  End With
End Sub

' searches the sub-items of hBaseItem *and the sibling items of hBaseItem*
Private Function FindNextMatchInSubTree(hBaseItem As Long) As Long
  Dim hNext As Long
  Dim l As Long

  With ETV
    ' make sure the sub-items have been loaded
    .ItemLoadSubItems hBaseItem
    hNext = .ItemGetFirstSubItem(hBaseItem)
    If hNext = -1 Then
      ' the item does not have any sub-items, so try the next sibling item
      hNext = .ItemGetNextItem(hBaseItem)
    End If
    Do While hNext <> -1
      ' we've found an item to investigate
      If ItemMatchesFilters(hNext) Then
        FindNextMatchInSubTree = hNext
        Exit Function
      End If

      ' this item doesn't match the filters, so investigate its sub-items
      l = FindNextMatchInSubTree(hNext)
      If l <> -1 Then
        ' a result has been found
        FindNextMatchInSubTree = l
        Exit Function
      End If
      ' no result has been found, so try the next sibling item
      hNext = .ItemGetNextItem(hNext)
    Loop
  End With
  FindNextMatchInSubTree = -1
End Function

Private Function ItemMatchesFilters(hItem As Long) As Boolean
  With ETV
    If .ItemIsPartOfFileSystem(hItem) Then
      ' the item is of a type that can be filtered
      If (.ItemIsFile(hItem) And .UseFileFilters) Or (.ItemIsFolder(hItem) And .UseFolderFilters) Then
        ' filters are activated for this item type, so the item must match the filters
        ItemMatchesFilters = True
      End If
    End If
  End With
End Function
Crunching for Fab36_Folding-Division at Folding@Home. Join Fab36/Fab30! - Folding@Home and BOINC
Boycott DRM! Boycott HDCP!
aka
Lieutenant
Posts: 17
Joined: 05 Jan 2006, 12:27

Re: Filter Results

Post by aka »

Hi TiKu,

sorry for my late reply. I did not had the time to test your last post earlier. It is a really big step forward and I owe you at least a TerraByte of thank. Unluckily, the code still is working correct only with limitations. These limitations are related to the up or down changing of the level at which the last filter result was found. An example: Selecting directly the "TimoSoft" folder I send you, everythings works as expected. On my PC this folder is located on drive "G:\", where several other folders a stored above, some of them containing filter results too (please see attached screenshot). What happens is:

1. Selecting "G:\" and clicking on "Jump to Next Filter Result" without expanding any root folders before, makes "...affiliat.txt" visible and selected. Everything is fine until "...readme.txt" is reached. If this file is selected and you try to jump to the next filter result, the code stops searching and "...readme.txt" remains the selected item.

2. Expanding the folder "Axialis ..." by clicking it in the tree and then clicking "Jump to Next Filter Result" does not cause anything. From the display of the CPU load I can see the code working for a few seconds and then stopping without finding a result. BUT selecting its subfolder "IconWorkShop Sample" and clicking on "Jump to Next Filter Result" opens "MTS-TESTS->MTS-TEST 2009_05_24" and makes "Result-Names.txt" the selected item. This is correct, because this file is the next filter result after "...readme.txt".

3. A further click again does NOT jump to and open "TimoSoft", but remains at "Result-Names.txt".

4. Selecting folder "TimoSoft" and clicking several times, not only makes all filter results in this folder visible, but jumps to the following filter results in the root of "G:\".

Of course I tried out to figure out the reason for this strange behaviour (also with other drives/folders, the result is the same), but without success. Does it make any sense to you?

IMPORTANT: On your website I read, that this project is a hobby of you and I definetely don't want to be impudent or stress your nerves. So, if you are sick and tired of this topic, do me the favour to give me a short note: Hi aka, it is enough! Last but not least, because it seems to be very likely, that my idea to change the code for "Find Next" working the other direction, will cause unsolvable problems for me too. The whole matter is very much more difficult than I expected.

Best regards

aka
Demo_for_TimoSoft.zip
(8.06 KiB) Downloaded 552 times
ScreenShot of Demo.jpg
(94.13 KiB) Not downloaded yet
User avatar
TiKu
Administrator
Administrator
Posts: 832
Joined: 28 Sep 2004, 21:10
Location: München
Contact:

Re: Filter Results

Post by TiKu »

Try this:

Code: Select all

Private Sub Next_Filter_Result(ByVal hSelection As Long)
  Dim hNext As Long
  Dim l As Long

  With ETV
    hNext = FindNextMatchInSubTree(hSelection)
    If hNext = -1 Then
      ' try parent item's next sibling sub-tree
      hNext = hSelection
      Do
        hNext = .ItemGetParentItem(hNext)
        If hNext = 0 Then hNext = -1     ' special handling for ShowRoot = False
        If hNext = -1 Then
          ' we've reached the end of the tree
          Exit Do
        Else
          l = hNext
          hNext = .ItemGetNextItem(hNext)
        End If
        If hNext = -1 Then
          ' this parent does not have a sibling item
          hNext = l
        Else
          If ItemMatchesFilters(hNext) Then
            ' we've found a match
            Exit Do
          Else
            l = FindNextMatchInSubTree(hNext)
            If l <> -1 Then
              ' we've found a match
              hNext = l
              Exit Do
            End If
          End If
        End If
      Loop
    End If

    If hNext <> -1 Then
      ' we've found a result
      .SelectedItem = hNext
      .ItemEnsureVisible hNext
    End If
  End With
End Sub
Crunching for Fab36_Folding-Division at Folding@Home. Join Fab36/Fab30! - Folding@Home and BOINC
Boycott DRM! Boycott HDCP!
aka
Lieutenant
Posts: 17
Joined: 05 Jan 2006, 12:27

Re: Filter Results

Post by aka »

Hi TiKu:

I have a big problem: I don't know how to express my thanks in an appropriate way!
Thank you very, very much for your last post. Now the code is perfect and finds all filter results, no matter how deep thy are located in the tree and how "fare away" they are from the last result. It's fantatstic. Using this code I can try to make it working in the other direction for "Jump to Previous Filter Result".

Once again: a warm and honest thank for the fantastic control your great support!
God bless you and all the best for you!
aka
Post Reply