mIRC Home    About    Download    Register    News    Help

Print Thread
#215653 28/09/09 10:11 AM
Joined: Sep 2009
Posts: 6
D
Nutrimatic drinks dispenser
OP Offline
Nutrimatic drinks dispenser
D
Joined: Sep 2009
Posts: 6
Guys, is there any way I can make a script wait for a certain key to be pressed before continuing with the next part?

As an example, for those who speak old Sinclair BASIC:

10 PRINT "item 1"
20 IF INKEY$ <> "F4" THEN 20
30 PRINT "Item 2"
.
.
.

For thise that don't understand the old Sinclair way of doing things - Line 20 waits for a key to be pressed, then compares that keypress to the value for the F4 key. If F4 IS pressed, the program then executes from the nest line, else it executes line 20 again, and continues to do so til either F4 or the break key is pressed.

All I want to be able to do, if press F4 for the script to display the next item in the script, but not before.

I bet there's a real simple way to do this, only I can't seem to work it out.....

Joined: Aug 2006
Posts: 183
T
Vogon poet
Offline
Vogon poet
T
Joined: Aug 2006
Posts: 183
Short answer: Yes, but it requires using timers or com statements and is a bit annoying to do correctly.

Longer answer: I'm only going to go over the timer method here. Below this I'll give you a snippet for /sleep which is incredibly handy, but shouldn't be used if it can be avoided.

Note: While you can do this with any key, you'd need to either use a DLL or a PicWin to work with non-function keys.

Code:
Alias F5 { set %var 1 }

Alias CheckKeyPress {
if %var == 1 { unset %var | Do Stuff here }
else { .timerCKP 1 1 CheckKeyPress }
}


This won't do exactly what you want, but it'll be close. Basically, the alias will call itself one a second until you hit F5. Upon hitting F5 it will do whatever command you tell it to.

The issue here is that it isn't instant. If you press F5, there is up to a second of lag before the command you want to happen happens.

If it need to be instant (or close to it) you can use /timerCKP -m 1 1 which will use milliseconds instead. This is naturally more CPU intensive (but most computers build in the past few years can handle it with ease).

Enjoy.

Edit: forgot to give the /sleep snippet. (I did not create this, so no credit goes to me.)

Code:
/sleep {
  var %a = $ticks $+ .wsf
  write %a <job id="js"><script language="jscript">WScript.Sleep( $+ $$1 $+ );</script></job>
  .comopen %a WScript.Shell
  if !$comerr { .comclose %a $com(%a,Run,3,bstr,%a,uint,0,bool,true) }
  .remove %a
}


Usage: /sleep n (where n is the number of milliseconds you want the script to "sleep" for.)

When you use /sleep, Mirc will stop the execution of the current script and return control to the CPU. After the sleep ends, the CPU will go back to processing the rest of the script.

Code:
alias TestSleep {
echo -a Pausing for 5 seconds
sleep 5000
echo -a Unpaused.
}


Its VERY handy to use, though timers can generally be used to the same effect.

Last edited by Thrull; 28/09/09 11:42 AM.

Yar
Joined: Sep 2009
Posts: 6
D
Nutrimatic drinks dispenser
OP Offline
Nutrimatic drinks dispenser
D
Joined: Sep 2009
Posts: 6
Thank you very kindly :D:D

Joined: Jan 2007
Posts: 1,156
D
Hoopy frood
Offline
Hoopy frood
D
Joined: Jan 2007
Posts: 1,156
Simply make a variable that is $true if you are waiting for the key to be pressed.

Then when the key is pressed, if variable exists, do what youw ant.

Code:
alias key_ {
  set %key_ $true
  echo -a Ok Im waiting for you to press the key.
}

alias f5 {
  if (%key_) {
    echo -a I waited for the key to be pressed and you just pressed it.
    unset %key_
  }
}



Type /key_ to start this. Press F5 after.

Joined: Jul 2008
Posts: 236
S
Fjord artisan
Offline
Fjord artisan
S
Joined: Jul 2008
Posts: 236
Actually, most computers built in the last 15 years (providing they are 32-bit) will be perfectly fine with the 'sleep for 1ms' (or even the 0ms that you provided below)... The reason for this is that the functions do not guarantee that it will sleep for 1ms.

Quote:
The system clock "ticks" at a constant rate. If dwMilliseconds is less than the resolution of the system clock, the thread may sleep for less than the specified length of time. If dwMilliseconds is greater than one tick but less than two, the wait can be anywhere between one and two ticks, and so on.


So for a CPU where a tick is at the least, 40ms (which would be extremely slow), you're more likely to get 40ms or more of sleep time. That doesn't include task scheduling.

Quote:
If you specify 0 milliseconds, the thread will relinquish the remainder of its time slice but remain ready. Note that a ready thread is not guaranteed to run immediately. Consequently, the thread may not run until some time after the sleep interval elapses. For more information, see Scheduling Priorities.


The /timer -ch (catch-up, high definition timer) is more likely to get 0ms on average, though it could cause input to mIRC to appear to "hang" on slower machines. Use with caution.

Also beware, if you're going to use the wscript.sleep method, of ping timeout! Because mIRC is (educated assumption) a single-threaded application, it can't do anything else while you're calling Sleep(), so it'll hang for the sleeping period, and possibly ping timeout if you call Sleep() for too long. I wouldn't recommend using Sleep() for mIRC at all, unless you absolutely know what you're doing.

Last edited by s00p; 29/09/09 09:41 AM.
Joined: Jan 2007
Posts: 1,156
D
Hoopy frood
Offline
Hoopy frood
D
Joined: Jan 2007
Posts: 1,156
All of that is way too much work. Variables, or other stored data, can tell us if the machine is waiting for the key to be pressed. It can hold personal data to say only one person can press the button.


Joined: Aug 2006
Posts: 183
T
Vogon poet
Offline
Vogon poet
T
Joined: Aug 2006
Posts: 183
Soop: While what you say is true, I've heard of people running into issues using timer -m. I never have, and the cases I've heard have been few and far between, but it does happen. As for why it happened I have no idea, but best to post a small warning just in case this is one of those cases.

Truth be told, I tried using 100 timers all set to 0 0 and using -m. I had no slowdowns and the CPU usage for Mirc didn't go up measurably.

Also, using the wscript.sleep method doesn't cause Mirc to hang at all. I'm not sure why exactly as I have little understanding of com functions. Mirc keeps right on processing while wscript.sleep is being used.

Last edited by Thrull; 30/09/09 07:19 AM.

Yar
Joined: Oct 2003
Posts: 3,918
A
Hoopy frood
Offline
Hoopy frood
A
Joined: Oct 2003
Posts: 3,918
Everyone is confusing this issue...

As far as I see, this has nothing to do with delays or pauses.

All you seem to want is F4 to continue processing the script. This is easy:

Code:
alias f4 { do_work }
alias do_work { inc %var | echo -a I've done this %var times }


Base your "work" on the value that %var holds. Timers are not needed here.


- argv[0] on EFnet #mIRC
- "Life is a pointer to an integer without a cast"
Joined: Oct 2003
Posts: 3,918
A
Hoopy frood
Offline
Hoopy frood
A
Joined: Oct 2003
Posts: 3,918
This is inaccurate. WScript.Sleep causes the script engine layer to hang. No events or aliases will process so long as the single-threaded script layer is frozen.

The UI layer, however, is not running entirely within the same thread, so mIRC will *seem* responsive, but it is not really.

I've seen no real world use cases where the COM WScript.Sleep alias is at all useful. If you need a delay for a set time, use a timer, there are far fewer side-effects.


- argv[0] on EFnet #mIRC
- "Life is a pointer to an integer without a cast"
Joined: Sep 2009
Posts: 6
D
Nutrimatic drinks dispenser
OP Offline
Nutrimatic drinks dispenser
D
Joined: Sep 2009
Posts: 6
Thanks for the help here guys smile

All I've done it seems is to cause some kind of flame war. For that I apologise.

I've tried the various examples given, I can't make any of them work. I've obviously missed out somewhere on some simple modern programming concepts - I'm very much an 80's programmer where we had Z80's running at 4MHz, and FOR TO NEXT loops with GETKEY statements.

It's just as easy for me to open up the text I want to disply in notepad, copy and paste.

Thanks for all your efforts, and again, sorry for starting a flame war - best I not bother you guys anymore

Joined: Aug 2006
Posts: 183
T
Vogon poet
Offline
Vogon poet
T
Joined: Aug 2006
Posts: 183
Its hardy a flame war. We're merely have a polite disagreement. smile Often times there are LOTS of ways to do any given thing. I've offered some, others have offered other options. Use which ever one you feel best suits your needs.

Quote:
This is inaccurate. WScript.Sleep causes the script engine layer to hang. No events or aliases will process so long as the single-threaded script layer is frozen.


Actually, while I think I understand what you're getting at, this isn't quite true. Other scripts run just fine while using WScript.Sleep (I tested this out when I first got the snippet). Its true that it causes the currently executing script to "hang" but that's the whole intent.

Quote:
I've seen no real world use cases where the COM WScript.Sleep alias is at all useful. If you need a delay for a set time, use a timer, there are far fewer side-effects.


Yes, 99% of the time you can use timers to do exactly the same thing. However, there is the occasion where you're not sure how long the timer should run for, and if you need to know that in order for the script to run correctly, using this method can ensure that everything happens correctly.

Again, this is a fairly rare, but it does on occasion come up.

Back on subject. There is also a dll out there called whilefix.dll which makes mirc responsive while its running a while loop. http://www.mircscripts.org/comments.php?cid=2617 It is quite old, but as far as I can tell, it still works.

Quote:
I've tried the various examples given, I can't make any of them work. I've obviously missed out somewhere on some simple modern programming concepts - I'm very much an 80's programmer where we had Z80's running at 4MHz, and FOR TO NEXT loops with GETKEY statements.


If you post the code here, we're much more likely to be able to tell you why it isn't working and what you can do to fix it.

Last edited by Thrull; 30/09/09 12:21 PM.

Yar
Joined: Jan 2007
Posts: 1,156
D
Hoopy frood
Offline
Hoopy frood
D
Joined: Jan 2007
Posts: 1,156
Originally Posted By: DragonForce01
Guys, is there any way I can make a script wait for a certain key to be pressed before continuing with the next part?


All I want to be able to do, if press F4 for the script to display the next item in the script, but not before.

I bet there's a real simple way to do this, only I can't seem to work it out.....


There are a few ways to get this done. Don't think of it as a few lines of code where you halt processing between lines. Instead make complete code statements that do what you want. The action of the button press triggers a script, verses continuing the processing of the current one.


Code:
alias key_ {

  if (%key_x) {
    ;button has been pressed "continue script here"
    echo -a Button has been pressed. What should I do?

    ;unset %key_x variable to be ready for next time.
    unset %key_x
  }
  else {
    ;script starts
    set %key_ $true
    echo -a Im waiting for you to press the key.
  }
}

alias f5 {
  if (%key_) {
    echo -a I waited for the key to be pressed and you just pressed it.
    unset %key_

    ;acknowledge key has been pressed.
    set %key_x $true
    ;go to command
    key_
  }
}


This is a bit crude and long winded. You really would just put the desired command in the F4 alias unless you had other plans.

As you can see, you type /key_. In the key_ alias, since the variable %key_x hasn't been set it skips to the else section where it sets a variable telling you and mirc that it is waiting for a key to be pressed.

When the key (F4) is pressed, if this variable wasn't $true it would do nothing. But since you told it to wait for they key press it will do the command.

What you want it to do when the key is pressed hasn't been stated, but you can put it in the F4 alias, or put it in the key_ alias as I have shown.

As you can see, it isn't as linear as you were visualizing it. You don't stop a script from processing, you break up the scripts. You can either make a new alias or make a new if statement in an existing alias. Remember you can't call an alias from within itself unless you use a timer.

Looking at things from different perspectives can be the biggest hurdle when scripting.


Link Copied to Clipboard