[Webinar] Streamline your web hosting managementRegister Today

x
?
Solved

How can I assure that my particular ListBox will clear?

Posted on 1999-10-28
31
Medium Priority
?
205 Views
Last Modified: 2010-05-02
I am creating an application that allows one to recursively search for graphics files anywhere on a computer. The retrieved file names are added to a listbox control when they are found using the AddItem method.  I've set up the Search command button to change its caption to "&Reset" as soon as the user starts a recursive search; and when he/she clicks on "&Reset," the search stops and a procedure is called to clear the listbox control's file names.  Only one problem:  Sometimes the list box clears, and other times it does not.  I tried adding a timer control to the form with a short interval set to check for a reset, but it did nothing.  Any ideas?
0
Comment
Question by:ljklinsky
  • 11
  • 7
  • 5
  • +4
31 Comments
 
LVL 14

Expert Comment

by:mcrider
ID: 2165658
Set a global variable called StopSwitch:

Global StopSwitch As Boolean

Then set the switch to False when you start your search.

On the Search/Reset Button, do this:


Private Sub Command1_Click()
    If Command1.Caption = "&Reset" Then
        StopSwitch = True
        Exit Sub
    End If
    'OTHERWISE DO YOUR SEARCH...
End Sub


Then in your loop where you're loading the listbox, make sure you call DoEvents, and check to see if StopSwitch is TRUE..

If you find that StopSwitch is TRUE then:

Clear your listbox...
Set the Search/Reset button caption back to Search
and exit your subroutine...


Cheers!
0
 
LVL 1

Expert Comment

by:lehket
ID: 2165671
Try adding a DoEvents.  Possibly right after aborting the looking process, possibly right after clearing the list box.  

Depending on what is happening in your code, you may need to experiment to find the right place to add DoEvents, but chances are you are somehow getting into a situation where some resource-intensive processing is preventing other tasks from being performed.
0
 
LVL 8

Expert Comment

by:vettranger
ID: 2165797
lehket is correct. During a recursive search process like the one you describe, its unlikely that VB will have much of a chance to recognize and process other events. In a case like this, you do need a Doevents to let your VB program recognize and handle other system messages being given to your VB app (like a click on your Reset).

mcriders solution may well successfully perform the Reset after your recursive search is complete, but it unlikely to have any more effect (so far as allowing a reset DURING the search) than the code you already described.

Place the doevents command just above the line where you make the recursive Call.
0
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
LVL 14

Expert Comment

by:mcrider
ID: 2165812
Vettranger,

Did you even READ my answer...

"Then in your loop where you're loading the listbox, make sure you call DoEvents, and check to see if StopSwitch is TRUE.."

Cheers!

0
 
LVL 8

Expert Comment

by:vettranger
ID: 2165830
Apologies, I missed your doevents reference. However, with the doevents, all the other stuff above that is wasted code, since his event will properly process as soon as VB can accept the click event message.
0
 
LVL 14

Expert Comment

by:mcrider
ID: 2165890
Not wasted... Code example of how to do it.
0
 

Author Comment

by:ljklinsky
ID: 2166035
I'm going to print out all these comments now and try to figure this out.  I DO have, and have always had, a DoEvents statement in my recursive search procedure, like such:

intRetVal = DoEvents() 'Check for events (ex. Cancel).

I'm clueless, but hopefully some of your ideas will help.  I'll be back.
0
 

Author Comment

by:ljklinsky
ID: 2166216
I tried all of your suggestions to no avail.  I already had a flag set as mcrider suggested; vettranger was correct about the outcome (the clear only worked after a search was completed.  I made some other changes that helped, but didn't totally solve the problem.  99% percent of the time now, the darn listbox clears.  All I did was put a statement to clear it right when the &Search/&Reset command button is clicked (kludgy coding).  I experimented with DoEvents() until I nearly dropped.  The placement did not change the situation in the least.  Current situation: The listbox will NOT empty ONLY when the recursive search is in the WINDOWS directory or any of its subdirectories.  I'm totally stumped.  Any more ideas?
0
 
LVL 1

Expert Comment

by:lehket
ID: 2166222
At what point does the DoEvents occur?  It may simply be a matter of getting it placed properly.  Also, note this caution from the VB help files:

Caution   Any time you temporarily yield the processor within an event procedure, make sure theprocedure is not executed again from a different part of your code before the first call returns; this could cause unpredictable results. In addition, do not use DoEvents if other applications could possibly interact with your procedure in unforeseen ways during the time you have yielded control.
0
 
LVL 1

Expert Comment

by:lehket
ID: 2166229
My last post crossed in the mail with yours.  ;-)  The Windows directory is often the largest on a system, so this makes some kind of sense.  What is the code for your recursive search?
0
 

Author Comment

by:ljklinsky
ID: 2166240
Private Sub cmdSearch_Click()
'Initialize for search, then perform a recursive search.
    Dim strFirstPath As String
    Dim intintDirCount As Integer
    Dim intNumFiles As Integer
    Dim intResult As Integer
    lstPowerSearch.Clear 'Start with a clean list box.
    frmMain.cmdManualSearch.Enabled = False
    Call DisableEditDelete 'Disable Edit and Delete function.
    If cmdSearch.Caption = "&Reset" Then 'If just a reset, initialize and exit.
        ResetSearch 'If user chooses &Reset, then end the search.
        Exit Sub
    Else
        m_blnSearchFlag = False
        frmPowerSearch.cmdSearch.Caption = "&Reset"
    End If
'Update dirPowerSearch.Path if it is different from the currently
'selected directory, otherwise perform the search.
    If dirPowerSearch.Path <> dirPowerSearch.List(dirPowerSearch.ListIndex) Then
        dirPowerSearch.Path = dirPowerSearch.List(dirPowerSearch.ListIndex)
        Exit Sub    ' Exit so user can take a look before searching.
    End If
' Continue with the search.
    filPowerSearch.Pattern = cboSearchSpec.Text
    strFirstPath = dirPowerSearch.Path
    intintDirCount = dirPowerSearch.ListCount
' Start recursive directory search.
    intNumFiles = 0 ' Reset found files intIndicator.
    lblCount.Caption = intNumFiles
    intResult = DirDiver(strFirstPath, intintDirCount, "")
    filPowerSearch.Path = dirPowerSearch.Path
    cmdSearch.SetFocus
    frmMain.cmdManualSearch.Enabled = True
End Sub

Private Function DirDiver(strNewPath As String, intDirCount As Integer, strBackup As String) As Integer
'Recursively search directories from strNewPath down...
'strNewPath is searched on this recursion.
'strBackup is the origin of this recursion.
'intDirCount is the number of subdirectories in this directory.
    Static intFirstErr As Integer
    Dim intDirsToPeek As Integer
    Dim intAbandonSearch As Integer
    Dim intInd As Integer
    Dim strOldPath As String
    Dim strThePath As String
    Dim strEntry As String
    Dim intRetVal As Integer
    m_blnSearchFlag = True 'Set flag so the user can interrupt.
    DirDiver = False  'Set to True if there is an error.
    intRetVal = DoEvents() 'Check for events (ex. Cancel).
    If m_blnSearchFlag = False Then
        DirDiver = True
        Exit Function
    End If
    On Local Error GoTo DirDriverHandler
    intDirsToPeek = dirPowerSearch.ListCount  'How many directories below this?
    Do While intDirsToPeek > 0 And m_blnSearchFlag = True
        strOldPath = dirPowerSearch.Path 'Save old path for next recursion.
        dirPowerSearch.Path = strNewPath
        If dirPowerSearch.ListCount > 0 Then 'Get to the bottom.
            dirPowerSearch.Path = dirPowerSearch.List(intDirsToPeek - 1)
            intAbandonSearch = DirDiver((dirPowerSearch.Path), intDirCount%, strOldPath)
        End If
        intDirsToPeek = intDirsToPeek - 1 'Go up one level in directories.
        If intAbandonSearch = True Then Exit Function
    Loop
'Call function to enumerate files.
    If filPowerSearch.ListCount Then
        If Len(dirPowerSearch.Path) <= 3 Then 'Check for 2 bytes/character
            strThePath = dirPowerSearch.Path 'If at root level, leave as is...
        Else
            strThePath = dirPowerSearch.Path + "\" 'Otherwise put "\" before the filename.
        End If
        For intInd = 0 To filPowerSearch.ListCount - 1 'Add conforming files in this directory to the list box.
            strEntry = strThePath + filPowerSearch.List(intInd)
            lstPowerSearch.AddItem strEntry
            lblCount.Caption = Str(Val(lblCount.Caption) + 1)
        Next intInd
    End If
    If strBackup <> "" Then 'If there is a superior directory, move it.
        dirPowerSearch.Path = strBackup
    End If
    Exit Function
   
DirDriverHandler:
    If Err = 7 Then  'If Out of Memory error occurs, assume the list box just got full.
        DirDiver = True  'Create Msg and set return value intAbandonSearch.
        MsgBox "You've filled the list box. Abandoning search..."
        Exit Function  'Note that the exit procedure resets Err to 0.
    Else  'Otherwise display error message and quit.
        MsgBox Error
        End
    End If
   
End Function
0
 
LVL 8

Expert Comment

by:vettranger
ID: 2166251
I agree with lehkey, I think we'll need to look at this on a more detailed level. How are you finding the files? (Dir function, FSO, API?) I would suggest that possibly that loop is so tight that you need the Doevents in the file loop, rather than before the recursive call that I suggested earlier, but I have a feeling from your comment that you've probably already tried it there.
0
 

Author Comment

by:ljklinsky
ID: 2166285
Well, I've included the code above.  I borrowed the routine from Microsoft's MSDN CD.  I'll be honest; I don't totally understand the above code, being a relative beginner.  Recursion is way beyond my understanding at this point, though I definitely understand the need for DoEvents, etc.  I coded the rest of the program without any help from anyone, and all of my code works fine.  I'd be more than willing to give one of you all my points (85) if you know what's going on.  At any rate, you've all been very sweet to help this much.  Thank you

Leslee  
0
 
LVL 8

Expert Comment

by:vettranger
ID: 2166380
Here some better code to use as a basis for your search. Just grab the recursive search routine of the Dirwalk control you can download from the following link.

http://support.microsoft.com/support/kb/articles/Q175/2/14.ASP

I'm surmising from the code above that its using a directorylist control to do this. That's likely the least efficient of several possible techniques to search your directories.

Efficiency is important here too. It will decrease the time the search takes, and will also help out with your reset problem.

The Dirwalk code probably isn't the MOST efficient way to do this, but its a step up from using a directory list control, and you can make other improvements more easily from the Dirwalk code than you can the code above.

Let me know if you have any trouble getting to that page. You have to register your VB with the Microsoft web site to get to it, so occasionally someone has a problem getting to it.
0
 

Author Comment

by:ljklinsky
ID: 2166497
I was so excited, vettranger, to have another option.  But I have VB6, not version 5; and it specifies on Microsoft's site that it's for VB5.  This has not been easy!  Thanks anyway.
0
 
LVL 5

Expert Comment

by:AnswerTheMan
ID: 2166527
i can suggest you a simple thing to do :
1. when hitting the STOP button - set
   a BOOL flag to TRUE.
2. in your recursive function add
   before and after each line the code :

  if BoolFlag==True then
     lstFiles.clear
     exit function
  endif

3. if that's clears the list - start ommiting those entries, until you'll find the correct logical place it should be.

0
 
LVL 8

Expert Comment

by:vettranger
ID: 2166552
Re VB5. It only says its for VB5 because the control was written in VB5 days, and they never updated the article. It works perfectly in VB6, I've got in in four different VB projects where I needed quick code to find a user's file for them.
0
 
LVL 14

Expert Comment

by:mcrider
ID: 2166613
ljklinsky,

Try this example...

1) Start a new project.
2) Add a commandbutton and a listbox to Form1.
3) Paste the following code into the Declarations Section of Form1, and run the program.
4) Click the "Start" button and Items will be added to the listbox in 1 second intervals... If you click the "Stop" button, List1 will be cleared.  If you wait 30 seconds, you will have a list that contains 30 items.

Cheers!

THE CODE:



Public StopSwitch As Boolean
Private Sub Command1_Click()
    Dim iVal As Long
    Dim myTimer As Long
   
    If Command1.Caption = "&Stop" Then
        StopSwitch = True
        Exit Sub
    End If
    'THIS IS WHERE YOUR SEARCH GOES USING DOEVENT...
    'HERE I'M LOADING ITEMS INTO THE LISTBOX
    'ONCE A SECOND TO SIMULATE A LONG SEARCH
    'THIS IS WHERE THE DOEVENTS AND STOPSWITCH
    'CHECK GO...
    List1.Clear
    StopSwitch = False
    Command1.Caption = "&Stop"
    For iVal = 1 To 30
        DoEvents
        'wait my one second
        myTimer = Timer + 1
        Do While myTimer > Timer
            DoEvents
        Loop
        List1.AddItem "Item #" + CStr(iVal)
        If StopSwitch = True Then
            List1.Clear
            List1.Refresh
            Command1.Caption = "&Start"
            Exit For
        End If
    Next iVal
End Sub
Private Sub Form_Load()
    Command1.Caption = "&Start"
End Sub
0
 

Expert Comment

by:moterk
ID: 2166946
try sometinng like this:


Dim SearchOK As Boolean
Sub Command1_MouseUp (Button As Integer, Shift As Integer, X As Single, Y As Single)
    If Command1.Caption = "&Reset" Then
        Command1.Caption = "&Start"
        ResetSearch
    Else
        Command1.Caption = "&Reset"
        StartSearch
    End If
End Sub
Sub StartSearch ()
    SearchOK = True
    Dim alldone As Boolean
    Do Until alldone
        alldone = getnextfile()
        DoEvents
        If SearchOK = False Then
            filelist.Clear
            Exit Do
        End If
    Loop
End Sub
Sub ResetSearch ()
    SearchOK = False
End Sub
Function getnextfile () As Boolean
    dim returnvalue as boolean
    'code to get next file newfile$
    'if last file then return false
    'else return true
    filelist.AddItem newfile$
    getnextfile = returnvalue
End Function
0
 

Author Comment

by:ljklinsky
ID: 2167057
Wow!  So many things to try! :))  

mcrider:  I tried your above code.  It worked really well, but it's way slower than the code I've got right now.  For hard disks with many files, I'm afraid that your scenario wouldn't work fast enough.  Nonetheless, I've learned a lot from it and will study it further.  Thank you.

vettranger:  I will definitely go to MS's site and download that component; and I appreciate your feedback on the VB6 issue.  But because my application is basically coded and sub-coded into the current recursion method, I'm afraid to switch to something totally new for searching files.  It would be like starting from scratch, and this scares me (since my project is 99% functional right now.
0
 
LVL 8

Expert Comment

by:vettranger
ID: 2167105
I think you'll find it very easy to try out the Dirwalk code. I took their recursive search procedure and just dropped it right into an application I did with very little change to it.

(I also dropped it into another project and replaced the Dir function it uses with the File System Objects, which was pretty neat and seemed faster.)
0
 
LVL 14

Expert Comment

by:mcrider
ID: 2167138
ljklinsky

The reason my example is slow is there is a 1 second timer in the loop...

Take it out, and it will speed up...

The timer was only there for the demonstration...


Cheers!
0
 

Author Comment

by:ljklinsky
ID: 2167213
Geez :(  I'm getting nowhere extremely fast!  

mcrider:  Point well taken, but I have no idea how to implement your idea in my present code.  Being a beginning/intermediate-level programmer, I'm lost there.  I'm sorry, but I totally appreciate the help you tried to give me.

vettranger:  After I did the most horrible kludge (when the user presses Reset, the listbox forecolor is changed to white!), I went to MS's site for the file you recommended.  The file does not exist there any more, apparently.  I searched all over their site, and could only find one reference to DirWalk.  When I got there, I clicked on Download, and the darn site said file doesn't exist. :( (cont. on next)
0
 

Author Comment

by:ljklinsky
ID: 2167227
AnswerTheMan:  I tried like heck to make your idea work, but I had no idea what to do.  I'm utterly confused now.

moterk:  I tried your idea, but got totally lost because I don't know how to use the GetFile() function to search through even one directory and place the files in my listbox.

I'm sorry all.  I really tried.  Thank you all, again.
0
 
LVL 8

Expert Comment

by:vettranger
ID: 2167326
I just downloaded the file from the site I posted above. Again I emphasize that you do have to register your VB product before you can gain access to that download area.
0
 
LVL 5

Expert Comment

by:AnswerTheMan
ID: 2167379
if the sky above you grows dark and full of clouds - that's the time to add another empty ListBox which be kept Unvisible until the STOP moment.
then you make it visible and make the other one - Unvisible. place them both on same location.
this one always work....
0
 

Author Comment

by:ljklinsky
ID: 2167421
Could a day feel any longer?  Geez, vettranger.  I'm a registered user of VB6 professional.  I clicked on the link above and got the following message:

The page cannot be found
The page you are looking for might have been removed, had its name changed, or is temporarily unavailable.

It didn't even give me the opportunity to enter my product ID or anything, never got that far.

I did more searching of MS's site, and the only link took me back to the page with that message.  If you'd like to send the file to me, I'd appreciate it.  I'd be happy to tell you my ID or whatever.  ljklinsky@earthlink.net
0
 
LVL 5

Expert Comment

by:AnswerTheMan
ID: 2167460
add that other list. what are you waitin for ?
0
 

Author Comment

by:ljklinsky
ID: 2167558
Actually, AnswerTheMan, don't you think that my kludge is just as kludgy as yours?  I think we're two of a kind!  I just turn the text white to match the listbox's background color any time the user clicks the Reset command button; and I turn it back to black when a Search starts!  In either case, however, I don't think people looking at my code will be terribly impressed by either method.  Maybe I can hide the lines of text when I print the code out, maybe just white it out or something! <wink>

Leslee
0
 

Author Comment

by:ljklinsky
ID: 2167640
vettranger:  I got the DirWalk file.  I had to contact MS, and they helped me retrieve it.  I saved its code to an OCX and successfully registered it.  It looks interesting, but I want to try the sample code before I tear up my application.  I put the DirWalk control on my form, along with a TreeView control as was specified.  I pasted MS's code into the General Declarations section of the form.  When tried running the project it bombed with this message:  "Compile error.  User-defined type not defined."  This was referring to this first line of code after Option Explicit:  

Dim nodX As ComctlLib.Node

I don't get it.  Do you?
0
 
LVL 96

Accepted Solution

by:
Bob Learned earned 200 total points
ID: 2168963
I started out using the DirWalk code, and through time simplified it.  The following code uses recursion.  I modified it slightly to allow a reset.  The form has a list box to hold the files, a command button 'Load' to start the process, and a command button 'Reset' to stop the process in the middle.  The project includes a reference to Micro$oft Scripting Runtime.  

Private bReset As Boolean
Private fsoDirWalk As New Scripting.FileSystemObject
Private foldMain As Scripting.Folder
Private foldCurrent As Scripting.Folder
Private fileCurrent As Scripting.File

Private Sub LoadDirectory(sDirectory As String)

   Set foldMain = fsoDirWalk.GetFolder(sDirectory)
   
   For Each foldCurrent In foldMain.SubFolders
      If bReset Then
         GoTo ExitSub
      End If
     
      LoadDirectory foldCurrent.Path
     
      DoEvents
     
   Next foldCurrent
   
   For Each fileCurrent In foldMain.Files
      frmOpenDoc.lstFiles.AddItem foldMain.Name & "\" & fileCurrent.Name
   Next fileCurrent
   
ExitSub:
   
End Sub

Private Sub cmdLoad_Click()

   bReset = False

   LoadDirectory "D:\"
   
End Sub

Private Sub cmdReset_Click()

   bReset = True
   
End Sub


I realize that you don't want to change in mid-stream, but I have found that this routine works fairly quickly.  I also realize, though, that it is hard to really tell when running on a Pentium III 500 MHz with 256 MB RAM.
0

Featured Post

The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Background What I'm presenting in this article is the result of 2 conditions in my work area: We have a SQL Server production environment but no development or test environment; andWe have an MS Access front end using tables in SQL Server but we a…
Since upgrading to Office 2013 or higher installing the Smart Indenter addin will fail. This article will explain how to install it so it will work regardless of the Office version installed.
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…

607 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question