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 Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How Can I Pause a VB Program? 2

Status
Not open for further replies.

barrytraver

Programmer
Nov 28, 2000
40
0
0
US
Is there any easy way to pause execution of a VB program temporarily other than by using a MsgBox ("Click OK when ready to continue.") or by adding a modal form with a similar message?

Anyone have any suggestions?

Barry
 
Use the Sleep API to cause you program to pause for a set number of milliseconds.


API Declaration
Private Declare Sub Sleep Lib "kernel32" Alias "Sleep" (ByVal dwMilliseconds As Long)

Usage
Call Sleep(30000) '**Pauses application for 30 seconds.
- Jeff Marler
(please note, that the page is under construction)
 
Jeff,

Thanks for the response.

How about, however, the situation where you want to let the user decide when to continue, but don't want to let him access any of the controls except, say, an OK button?

In short, I'm after the equivalent of a MsgBox, but without using the MsgBox (whose location cannot be controlled) and without adding a modal form (because that's one more file for the project and I don't want to add it unless it's absolutely needed)?

The best I've been able to come up with so far (and it's not that great and I don't even know if it will work) is to set (in code) the Tabstop property of all of the controls (except the OK button) temporarily to False (and then change them back to True after the OK button is clicked).

Sample situation: you're writing a quiz program. When the user gets a question wrong, he is shown the correct answer and told to click OK after he has studied the proper response. After he clicks OK (and not before then), the next question is shown.

Any additional thoughts, anyone?

Barry
 
I thought of one way to do it, although it may not be the best way.

Here it is: Declare a global variable named Pause as Boolean. At the beginning of each control event procedures (other than, say, an OK button) insert the following line:

If Pause = True Then Exit Sub

To pause the program, simply set Pause to True. To resume normal execution, simply set Pause to False. (Of course, there must be some way to re-set Pause to False or the program would essentially "freeze.")

Does nnyone have any other ideas on how to approach the task?

Barry

P.S. My earlier idea about possibly setting the Tabstop property to False was not a very good one.
 
I 'think' I would - when "Pausing", I would set focus to the "O.K." command button. In the got focus of the O.K. button, I would do a (Brief) Sleeptimer, and - on return, do another set focus on the O.K. button. You might need a short Loop of do nothing in this to allow the click event a way to be recognized.


MichaelRed
redmsp@erols.com

There is never time to do it right but there is always time to do it over
 
Remember that VB is Event Driven . . . the application will not move forward all by itself . . . it needs an event. That may be the user click ok, next question, or a timer evert. And you have programmatic control over all of the events that VB responds to.
Using your test example . . . if you want the user to stop on a current question until they click OK, then simply set the focus to the OK button and then set {control}.Enabled = False to every other control that will fire an event that your application will respond to. When the user clicks OK, go ahead and re-enable the other disabled controls. This stop the user from moving forward and gray out all other controls on the SINGLE form so that the user knows they have to click OK. - Jeff Marler
(please note, that the page is under construction)
 
I found another way to do it, which is super-simple and seems to work great, so there must be something wrong with it! <grin>

Here's the procedure (and global variable needed):

Dim gPause as Boolean

Sub Pause()
gPause = True
Do
If gPause = False Then Exit Do
DoEvents
Loop
End Sub

And here's a simple way to test it. Put two command buttons on a form along with these click procedures:

Private Sub cmdTryIt_Click()
Print &quot;Before&quot;
Call Pause
Print &quot;After&quot;
End Sub

Private Sub cmdResume_Click()
gPause = False
End Sub

Click on the &quot;Try It&quot; button, and &quot;Before&quot; will be printed on the form. The program will stay paused until you click on the &quot;Resume&quot; button, at which time &quot;After&quot; will be printed on the form.

It can't be this simple. Or can it? Does anyone see any disadvantages to this approach?

Barry
 
yes Barry, your code will work, but take atr lok at your CPU utilization while the code is in the Do Loop . . . it is pegged at 100% . . . not a big deal as long as your application is the only one running, but not good for mulitasking. - Jeff Marler
(please note, that the page is under construction)
 
Jeff,

Thanks for your comments. I knew my approach was too good to be true.

After all this discussion, let me restate what I'm after. What I want is the ability to place a user-controlled pause somewhere in the middle of a procedure:

...
Do some stuff (involving lots of local variables)
Pause (length of time under user control)
Do some other stuff (with same local variables)
....

Here's how that could be done in QBASIC, QuickBASIC, etc.:

....
Do some stuff
Print &quot;Press enter when ready to continue.&quot;
Input M$
Do some other stuff
....

Here's one way to do it in Visual Basic:

....
Do some stuff
MsgBox &quot;Press OK when ready to continue.&quot;
Do some other stuff
....

Here's another way to do it in Visual Basic

....
Do some stuff
frmMessage.Show vbModal
Do some other stuff
....

Now here's the question: what's another good way to perform the task?

Note well: the &quot;some other stuff&quot; has to be able conveniently to make use of the local variables used in &quot;some stuff.&quot; Trying to pass them as parameters to a different procedure would be a mess. So the pause has to be able to work in the middle of a procedure (I know how to do it if the &quot;some stuff&quot; and the &quot;some other stuff&quot; could be in different procedures.)

Is there anything similar to my DO LOOP approach which would not monopolize CPU usage so drastically? Someone mentioned something about possibly using the timer control, but I haven't figured out how to write the code to make that work.

I know, the obvious solution is to use a modal form (and I can do that), but is it impossible to do in Visual Basic what was so easy to do in QBASIC?

Thanks for your thoughts.

Regards,

Barry
 
Barry, I think you're trying to have your cake and eat it, too. The reason you could do it easily in QBasic but not in VB is that QBasic has an MS-DOS interface--in which the user responds to the program--while VB has a Windows interface--in which the program responds to the user. It's not so much QB vs. VB as MS-DOS vs. Windows. And yes, programming for Windows is harder, that's a given.

It's true that what you're trying to do is give the user control, but only with respect to the OK button.[/i] With respect to all the other controls, you want the program calling the shots, and limiting the user to a single course of action. That's inimical to Windows design, and that's why it's tough to do.

But even in Windows, sometimes this is necessary, so Windows has application and system modality specifically to handle these situations. That's what modal forms are for! So shying away from using them is cutting off your nose to spite your face.

BTW, I don't think your tight loop with DoEvents gets you there. If the user clicks another control, that control will still receive the event (though it might respond sluggishly, with your loop eating up so much CPU time). Some events may get hung up waiting for whatever event started your Pause loop to exit, but some won't. And any that do will still run after the OK button is clicked.

If I were you, I'd go with the flow and use an application modal form, instead of trying to buck Windows. It's not nice to fool mother Microsoft! Rick Sprague
 
Rick,

Thanks for your thoughts, even though I still think that &quot;elegant simplicity&quot; (e.g., being able to put an entire working program into a single file which may serve as a useful teaching example) can be a noble goal.

Here's an improved Pause subroutine, which doesn't tie up the CPU in as wasteful a fashion:

Private Declare Sub Sleep Lib &quot;kernel32&quot; (ByVal _
dwMilliseconds As Long)
Dim gPause As Boolean

Sub Pause()
gPause = True
Do
Sleep 100
If gPause = False Then Exit Do
DoEvents
Loop
End Sub

Of course, you also have to disable temporarily the controls that you do not want the user to use, but that's not difficult to do. If controls are disabled, the user won't click on them (yes, I have given in to actually disabling them), and the Sleep command means that the loop doesn't eat up much CPU time.

Anyway, the Pause subroutine approach (including the Sleep command) seems to work fine (at least on the two machines I've tried it on so far, one running Windows ME and the other a slower machine running Windows 95).

By the way, I am willing to &quot;go with the flow&quot; when there is no reasonable alternative, but I do like to explore other possibilities off the beaten path (if I can mix some metaphors here).

Any decent programming language ought to allow a flexible combination of mudular programming and linear programming.
You say to me, &quot;you want the program calling the shots, and limiting the user to a single course of action. That's inimical to Windows design, and that's why it's tough to do.&quot; And my reply is, &quot;If that's true, so much the worse for Windows, if it is 'inimical' to 'limiting the user to a single course of action.' A program -- and a programmer -- ought to be free sometimes to 'call the shots,' because often straight-line development is the best way to go.&quot;

Thanks again for your thought-provoking comments. I'm still not convinced by what you say (but then again, I'm not a professional programmer -- I program primarily not for a living, but for fun).

Warm regards,

Barry
 
Barry,
A few quick comments . . . . Windows programming is very easy to work within and the is not limiting at all once you understand how the framework works. However, making that initial jump to the framework can be hard because it requires that you think differently. As far as you saying, &quot;though I still think that elegant simplicity (e.g., being able to put an entire working program into a single file which may serve as a useful teaching example) can be a noble goal.&quot; I would have to disagree with you. Current OOP/COM development technology (the same technology used in devloping n-teired applications) requires that your programs being broken up into many different files . . . and this paritioning of you application is not just on the code level . . . it is actually on the binary file level. But if you can do it, you can do some really amazing stuff!
Ok, having said that, here are some thoughts on your last piece of code which I have copied here . . .


Sub Pause()
gPause = True
Do
Sleep 100
If gPause = False Then Exit Do
DoEvents
Loop
End Sub


This is more CPU friendly (now that you've added the sleep command) that you first option (where it was just spinning) and I am sure that this option will work fine for you (since you require having all of your code in the same routine). However with the sleep command, remember that the applications actual thread goes to sleep and this may make your program seem sluggish while it is waiting for the user to click the button to move forward. With that in mind replace you Sleep API call with the WaitMessage API. This will force the application to stop and wait for any message from the OS. This means that the moment the user click the button, a message will be issued, and the API will release the thread of execution. Here is the code. . .



Private Declare Function WaitMessage Lib &quot;user32&quot; Alias &quot;WaitMessage&quot; () As Long


Sub Pause()
gPause = True
Do

Call WaitMessage()

If gPause = False Then Exit Do
DoEvents
Loop
End Sub


This will do the same thing as your sleep implementation, but it will be much more responsive. This WILL NOT use up excess CPU cycles. Hope this helps! :)
- Jeff Marler
(please note, that the page is under construction)
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top