Click to See Complete Forum and Search --> : Looping a Sub or Function


ABASYYX
June 29th, 2001, 06:54 PM
I need to know how to loop a Sub or Function without freezing the program. It's basically something simple. I'm moving around the screen a circle that changes sizes and colors as it goes. I prefer not to use a Timer Object to do this (although it works without freezing, it's too slow). When I try to have my Sub call itself at the end of itself, the program freezes. How should I get this done?

Captain Nuss
June 29th, 2001, 07:08 PM
I'm not an expert in such issues, but try inserting a DoEvents statement into your loop.

----------------
You can contact me directly at Christoph.Schulze@gmx.co.uk
Hey, and... don't forget your parsley cause you can't eat your dog after having stolen him from some animal shelter and having drowned him in the Atlantic Ocean.

sotoasty
June 29th, 2001, 09:26 PM
Although You can "loop" a sub or function (it's called recursion), you will quickly get into trouble unless you provide an escape route. When you call a sub from itself, the program keeps a pointer to the original location (normally by pushing this location onto the stack). So if you keep calling the sub from within itself, there is no way for the program to resume it's normal execution, and you will get an error, out of stack space. What you might want to try is something like this.


option Explicit
private MyExit as Boolean

private Sub Command1_Click()

MyExit = true

End Sub

private Sub Form_KeyUp(KeyCode as Integer, Shift as Integer)

If KeyCode = 13 then
MyExit = true
End If

End Sub

private Sub Form_Load()

me.Show
MyExit = false
Call DoMyLoop

End Sub

private Sub DoMyLoop()

Do Until MyExit
DoEvents
Call MoveMyCircle
Loop
MsgBox "Stopped"

End Sub

private Sub MoveMyCircle()

' code to do what you want here.
End Sub

vampyre
July 1st, 2001, 09:45 AM
I frequently encounter these type of loops. Recently, I started using an alternative to the VB Timer Control, the timer API functions. This kind of timer is much quicker and more consistent than the control.

First, you must place the required API functions in a module. You can load these using the VB API declaration loader add-in, but I've printed them below:

public Declare Function SetTimer Lib "user32" Alias "SetTimer" (byval hWnd as Long, byval nIDEvent as Long, byval uElapse as Long, byval lpTimerFunc as Long) as Long
public Declare Function KillTimer Lib "user32" Alias "KillTimer" (byval hwnd as Long, byval nIDEvent as Long) as Long



If this looks complicated to you, don't worry, it's easier than it looks.
Next, make a public function or public sub in a module. This can be the same as you put the functions in, as long as it's public. In that function, you can place all code to move the circle as you like.
Now, you must make sure that your code gets executed. In the form_load event of your form, place code like this:

Call SetTimer(me.hwnd,1,howfastitgoes, AddressOf yourfunction)



It's a simple call: Me.hwnd is the handle to your form; 1 is the number of the timer event (because you can have more timers on a single form, each event needs to have it's own Id number). Replace howfastitgoes with a number representing the number of milliseconds to wait each time before the function is called. Finally, replace yourfunction with the name of the function you placed the code in. Now, every [howfastitgoes] millisecs, youf function will be executed and the circle will move. The API timer is really fast!
Now you only need to make sure that your function stops being called after the form closes. Place the following code in your form_unload event:

Call KillTimer(me.hwnd, 1)



You don't have to worry about all this being too difficult; you can just paste the code into your project and change the arguments to what I said. Good luck!