Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

DoEvents & cancel button not working. How to fix?

Status
Not open for further replies.

MissouriTiger

Programmer
Oct 10, 2000
185
US
This is really strange. My program is essentially a loop, whose terminating condition is a boolean flag called blnPause which is set to true when the user clicks 'Pause'. It runs either until it finds something it is looking for, or until the user clicks either the 'Pause' or 'Exit' button.

But the thing runs so fast that the click events for the buttons go unnoticed. So I added DoEvents and a timer, which shuts itself off after one half second, and use the following loop to fire DoEvents and to check when the timer is done:

objPauseTimer.Enabled = True 'Timer will turn itself off

Do Until pauseTimerDone
DoEvents
Loop
pauseTimerDone = False 'Reset

This still isn't enough. What should I do? Should I make the timer run longer? Maybe a full second? Maybe 2 seconds? Maybe an hour? I mean, how can I be certain what time frame is going to be sufficient?

Isn't there a way to just ask the system if there are any events and use the answer to that request as the terminal condition of a loop? Something along the line of this:

Do Until MyProgram.HasEventsInQue = false
DoEvents
Loop

Any suggestions would be much appreciated.


Greg Norris
Software Developer

________________________________________________
Constructed from 100% recycled electrons.
 
It's strange. This code even with no timer works at my PC:
Option Explicit

Private mblnStop As Boolean

Private Sub Command1_Click()
mblnStop = True
End Sub

Private Sub Command2_Click()
mblnStop = False
Do Until mblnStop
DoEvents
Loop
MsgBox mblnStop
End Sub

vladk
 
First off: timer messages are of such a low priority that they may very well get "lost"during application process.

Second: in order to be able to respond to events (such as timer events), your app must be in an idle state, which it will never be inside a loop...... unless you do as vladk says and put the DoEvents() inside the loop so that your app actually gets the chance to respond to events.

Greetings,
Rick
 
That's exacftly what I'm doing, and it only works sometimes. Yes, every iteration of my loop calls DoEvents. Nonetheless, half the time you click the Pause button the program keeps right on going.

Greg Norris
Software Developer

________________________________________________
Constructed from 100% recycled electrons.
 
Have the timer event print debug messages; that way you can at least notice if your timer events come through (which I doubt.....)

Greetings,
Rick
 
Good idea, I'll try that. But even if they don't, I have a DoEvents method in my loop that is being called every iteration regardless of the timer.




Greg Norris
Software Developer

________________________________________________
Constructed from 100% recycled electrons.
 
Greg,

Here's what I did. First, I have two forms. One form opens another form. The first form has in its Activate event the waiting loop. The second form has the timer with that will set the pauseTimerDone flag. The pauseTimerDone flag is declared in a module as public. Form1 has a private flag bFirstLoad, so that I can load the forms without going into the Do..Loop until I'm ready. Form2 has a timer and it's interval is set to 1 second and it is enabled in Form2_Activate() event. Click back and forth between the two forms and see that everything works fine.

Code in Form1 (has a label lblJunk):
Code:
Private Sub Form_Activate()
   If (bFirstLoad) then
      bFirstLoad = False
      Form2.Show 
   Else
      lblJunk.Caption = "pauseTimerDone = " & IIf(pauseTimerDone, "TRUE", "FALSE")
      lblJunk.Refresh

      Do Until (pauseTimerDone)
         DoEvents
      Loop

      lblJunk.Caption = "pauseTimerDone = " & IIf(pauseTimerDone, "TRUE", "FALSE")
      lblJunk.Refresh
   End If
End Sub

Code in Form2 (with a text box txtFocus:
Code:
Private Sub Timer1_Timer()

   Static myCount as integer

   myCount = myCount + 1
   txtFocus.Text = CStr(myCount Mod 3) & "     " & CStr(myCount)
   txtFocus.Refresh

   If (myCount Mod 3 = 0) Then
      If (pauseTimerDone) Then
         pauseTimerDone = False
      Else
         pauseTimerDone = True
      End If
   End If

End Sub

I can see that the timer is functioning and that the Do..Loop is also executing. This happens whenever Form1 loses focus, then gets focus.

Hope this helps.

HyperEngineer
If it ain't broke, it probably needs improvement.
 
You have this (probably inside your main loop....?)

Do Until pauseTimerDone
DoEvents
Loop

And I assume that pauseTimerDone is set inside the event handler of the timer control. It is likely that you don't even get out of this little loop.....


I suggest you get rid of the timer and just put one (or more, depending on the amount of processing inside the main loop) DoEvents() in the main loop; that should work....



Greetings,
Rick
 
Rick,

The evaluating do loop is done inside the Form1_Activate() event (main form). But it doesn't do it on the first activate. On all subsequent activates it is triggered.

The pauseTimerDone is controlled by the timer control in Form2. This toggles the flag so that I can repeat the sequence of events.

When the program starts, Form1 loads Form2. The do loop is not entered because this is the first time Form1 is loaded.

When I click on Form2 the timer is enabled and the interval is set to 1 second. So the timer runs continuously. If I click on Form1, this is not the first time the form is activated, so the do loop is entered. If pauseTimerDone is True the loop is not even entered. If pauseTimerDone is False, then the loop is entered and it monitors the state of the flag. When pauseTimerDone is True, the loop is exited. The loop will not be entered again until Form1 loses focus the regains the focus.

It works, I tried it.

Thanks,

HyperEngineer
If it ain't broke, it probably needs improvement.
 
There is one peculiarity with the program. And that's because it is just to test the problem at hand. But in reality the loop should be exited before the program tries to terminate. If we are in the loop looking for the true condition, but we terminate Form2, the loop is then never exited. This will cause it to hang and brute force is required to remove it. Either via the End icon in the IDE or through the Windows Task manager. But this should not happen in a real program. The program should be in an idle state, or able to get to the idle state when the request to terminate is made.

HyperEngineer
If it ain't broke, it probably needs improvement.
 
HyperEngineer,

I wasn't refering to your post; I hadn't even seen the subsequent posts, since I was on the phone while editing my post and the subsequent posts were not there when I started editing my last post.....

I was refering to the very first post of the OP.....

Greetings,
Rick
 
Rick,

Good. I thought I might have been a little confusing. Hard to get everthing into these posts.

But I agree with you. We need to see some code.

HyperEngineer
If it ain't broke, it probably needs improvement.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top