Solved

VBScript "Do Until" keypress   -   Possible?

Posted on 2012-03-27
15
3,614 Views
Last Modified: 2012-03-29
Experts,

I'm playing with a VBScript that's using the SAPI.SpVoice - and it's going fairly easily...

Except, sometimes the computer can be fairly long winded when it's reading one of my variables I'm feeding it.

Currently, the script is VERY basic, but I'd like to add the ability to make the computer STOP talking when I hit any key / mouse click.

Is this an option?


        Dim objSpeech

        Set objSpeech = CreateObject("SAPI.SpVoice")
        ReadString = "Blah blah blah . . ."

        objSpeech.speak ReadString, SVSFlagsAsync + SVSFPurgeBeforeSpeak

Open in new window




I was thinking of doing something like:

Do Until ***User presses a key / clicks the mouse***
    objSpeech.speak ReadString, SVSFlagsAsync + SVSFPurgeBeforeSpeak
Loop



If anybody has any ideas on how to make this happen, I would be very greatful.
0
Comment
Question by:usslindstrom
  • 9
  • 5
15 Comments
 
LVL 7

Assisted Solution

by:micropc1
micropc1 earned 25 total points
ID: 37775011
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 37775035
VBScript can't hook into Windows events to know when a key is pressed or the mouse is moved, but if you were to build a HTA, then the windows.event.keycode method that micropc1 pointed to can be used.

When you launch the HTA, you can have it start reading the string, and capture any keypresses on the HTA's "form".

Regards,

Rob.
0
 
LVL 5

Author Comment

by:usslindstrom
ID: 37775188
Thank you both very much for the assistance.

I may need a bit more of a nudge if you guys have a few seconds.  Using this code (from the link that micropc1 provided)

I created a Boolian value that I'm "flipping the switch" on before and after the text to speech:

        SpeechInProgress = "True"

        objSpeech.speak ReadString, SVSFlagsAsync + SVSFPurgeBeforeSpeak

        SpeechInProgress = "False"

Open in new window



And then for testing I have the onClick for the Document...

Sub Document_onClick()
    If SpeechInProgress Then
        msgbox "Speech in Progress."
    Else
        Msgbox "No Speaka' da' Englais"
    End If

Open in new window




Unfortunately, the little program just sits and waits until the speech has finished, before it executes the SubRoutine.  Of course, once the speech api has finished, the 2nd msgbox is displayed.
0
 
LVL 65

Accepted Solution

by:
RobSampson earned 475 total points
ID: 37775865
Hi, here's a HTA that I just got working.  Save the code into a file with a .HTA extension, and run it.  Clicking the button will toggle the speech on and off.

Regards,

Rob.

<html>
<head>
<title>Test</title>
<HTA:APPLICATION 
	ID = "objHTA"
	APPLICATIONNAME="Test"
	BORDER="dialog"
	SCROLL="no"
	SINGLEINSTANCE="yes"
	WINDOWSTATE="normal"
	Maximizebutton="no"
	ContextMenu="no"
>
<html>
	<head>
		<script language="vbscript">
	        
	        Dim objSpeech, ReadString
	        Const SVSFPurgeBeforeSpeak = 2
	        Const SVSFlagsAsync = 1
	        
			Sub Window_OnLoad
				intWidth = 800
				intHeight = 600
				Me.ResizeTo intWidth, intHeight
				Me.MoveTo ((Screen.Width / 2) - (intWidth / 2)),((Screen.Height / 2) - (intHeight / 2))
	        	Set objSpeech = CreateObject("SAPI.SpVoice")
				blnSpeaking = False
	        	ReadString = "This is a test message to see whether the computer is speaking or not."
			End Sub

			Sub Speak
				If objSpeech.Status.RunningState = 1 Then
					objSpeech.Speak ReadString, SVSFlagsAsync + SVSFPurgeBeforeSpeak
				Else
					objSpeech.Speak " ", SVSFlagsAsync + SVSFPurgeBeforeSpeak
				End If
			End Sub			
			
		</script>
	</head>
	<body>
		<input type="button" id="btn_speak" name="btn_speak" value="Toggle Speech" onclick="Speak">
	</body>
</html>

Open in new window

0
 
LVL 65

Expert Comment

by:RobSampson
ID: 37775871
Note that I think one of your issues with it not showing the message until the speech finished is that you didn't have the constants defined with their values.

Rob.
0
 
LVL 5

Author Closing Comment

by:usslindstrom
ID: 37779722
Holy crap!  You just did all of my work for me.  :)

Sorry it took a bit to respond here.  I was reading into what you were trying to show me and understand it completely, instead of just copy/pasting.

As it turns out, your HTA worked absolutely flawlessly - but I couldn't get mine to do anything other than what was described before.  (The computer would drone on and on about mission statements.  :)  * I felt like I was attending regularly schedule office meetings.  :) )

You're comment about the constants got me in the right direction.  I didn't declare those constants at ALL.  - Unfortunately, as soon as I set them though the computer stopped talking completely.  Not a peep.

So, instead of delcaring the constants, I just threw them as their numbers after the objSpeech.speak ReadString, *HERE* arguments.  - And now it works as required.

I could not have put it together AT ALL without your help, and it's VERY much appreciated.  People around the office here are either going to love the option, or just get tired of Microsoft Sam all together.  Either or, it's shaping out to be some very cool stuff, all thanks to you.
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 37779750
OK, no problem.  I'm not sure why the constants didn't work for you, but yes, using their numeric values directly is another option.  Just so you now, I got the "status" code from here:
http://msdn.microsoft.com/en-us/library/ms722534(v=vs.85).aspx

You can change voices (if you have more installed), volume, pitch, and other cool stuff too.  Have a look through here:
http://msdn.microsoft.com/en-us/library/ms723602(v=vs.85).aspx

Finally, did you want help getting it to work based on pressing a key or moving the mouse?  That can be done, I'm sure....

Regards,

Rob.
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 5

Author Comment

by:usslindstrom
ID: 37779977
Now that it's working, actually - I'm thinking of doing an image swap in the HTML.

Currently, in order for the text-to-speech to get acted on, the user will click on a small speaker icon in the bottom right of the form.

I'm thinking at this point, now that everything's working VERY well (Thank you for your help) - That I'll keep the control to the "onclick" function of the button.

I think it would be VERY professional looking if I just swapped the speaker button to the same pic, but with a Circle and a Line through it indicated to the user to make the computer stop talking, they push the button again.

Not sure how I'm going to pull it off, but that's the thought process.
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 37780352
Hi, that sounds perfectly achievable.....one thing you might like to try doing is have the page also identify when the speech has stopped, and get it to change the "cancel" back to a "speak" button as well....I'll see if I can knock something up....

Rob.
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 37780369
Actually, turns out far easier that I though, utilising a HTML Timer control.

Check this out.  It uses text instead of images, but shouldn't be hard to change.

Regards,

Rob.

<html>
<head>
<title>Test</title>
<HTA:APPLICATION 
	ID = "objHTA"
	APPLICATIONNAME="Test"
	BORDER="dialog"
	SCROLL="no"
	SINGLEINSTANCE="yes"
	WINDOWSTATE="normal"
	Maximizebutton="no"
	ContextMenu="no"
>
<html>
	<head>
		<script language="vbscript">
	        
	        Dim iTimerID, objSpeech, ReadString
	        Const SVSFPurgeBeforeSpeak = 2
	        Const SVSFlagsAsync = 1
	        
			Sub Window_OnLoad
				iTimerID = window.setInterval("CheckSpeech", 500)
				intWidth = 800
				intHeight = 600
				Me.ResizeTo intWidth, intHeight
				Me.MoveTo ((Screen.Width / 2) - (intWidth / 2)),((Screen.Height / 2) - (intHeight / 2))
	        	Set objSpeech = CreateObject("SAPI.SpVoice")
	        	ReadString = "This is a test message to see whether the computer is speaking or not."
			End Sub

			Sub Speak
				If objSpeech.Status.RunningState = 1 Then
					objSpeech.Speak ReadString, SVSFlagsAsync + SVSFPurgeBeforeSpeak
					btn_speak.Value = "Mute"
				Else
					objSpeech.Speak " ", SVSFlagsAsync + SVSFPurgeBeforeSpeak
					btn_speak.Value = "Speak"
				End If
			End Sub			
			
			Sub CheckSpeech
				If objSpeech.Status.RunningState = 1 Then
					btn_speak.Value = "Speak"
				Else
					btn_speak.Value = "Mute"
				End If
			End Sub
		</script>
	</head>
	<body>
		<input type="button" id="btn_speak" name="btn_speak" value="Speak" onclick="Speak">
	</body>
</html>

Open in new window

0
 
LVL 65

Expert Comment

by:RobSampson
ID: 37780381
Here's another version that works with images ;-)

Rob.

<html>
<head>
<title>Test</title>
<HTA:APPLICATION 
	ID = "objHTA"
	APPLICATIONNAME="Test"
	BORDER="dialog"
	SCROLL="no"
	SINGLEINSTANCE="yes"
	WINDOWSTATE="normal"
	Maximizebutton="no"
	ContextMenu="no"
>
<html>
	<head>
		<script language="vbscript">
	        
	        Dim iTimerID, objSpeech, ReadString
	        Const SVSFPurgeBeforeSpeak = 2
	        Const SVSFlagsAsync = 1
	        
			Sub Window_OnLoad
				iTimerID = window.setInterval("CheckSpeech", 500)
				intWidth = 800
				intHeight = 600
				Me.ResizeTo intWidth, intHeight
				Me.MoveTo ((Screen.Width / 2) - (intWidth / 2)),((Screen.Height / 2) - (intHeight / 2))
	        	Set objSpeech = CreateObject("SAPI.SpVoice")
	        	ReadString = "This is a test message to see whether the computer is speaking or not."
			End Sub

			Sub Speak
				If objSpeech.Status.RunningState = 1 Then
					objSpeech.Speak ReadString, SVSFlagsAsync + SVSFPurgeBeforeSpeak
					span_speak.innerHTML = "<img id=""btn_speak"" name=""btn_speak"" src=""speaker_on.jpg"" onclick=""Speak"" onmouseover=""btn_speak.style.cursor='hand'"">"
				Else
					objSpeech.Speak " ", SVSFlagsAsync + SVSFPurgeBeforeSpeak
					span_speak.innerHTML = "<img id=""btn_speak"" name=""btn_speak"" src=""speaker_off.jpg"" onclick=""Speak"" onmouseover=""btn_speak.style.cursor='hand'"">"
				End If
			End Sub			
			
			Sub CheckSpeech
				If objSpeech.Status.RunningState = 1 Then
					span_speak.innerHTML = "<img id=""btn_speak"" name=""btn_speak"" src=""speaker_on.jpg"" onclick=""Speak"" onmouseover=""btn_speak.style.cursor='hand'"">"
				Else
					span_speak.innerHTML = "<img id=""btn_speak"" name=""btn_speak"" src=""speaker_off.jpg"" onclick=""Speak"" onmouseover=""btn_speak.style.cursor='hand'"">"
				End If
			End Sub
		</script>
	</head>
	<body>
		<span id="span_speak"><img id="btn_speak" name="btn_speak" src="speaker_on.jpg" onclick="Speak" onmouseover="btn_speak.style.cursor='hand'"></span>
	</body>
</html>

Open in new window

0
 
LVL 5

Author Comment

by:usslindstrom
ID: 37785227
ABSOLUTELY BRILLIANT!

When I implemented your last suggestion, it turned out better than I could have even imagined!

I'm going to be including your name in the script "credits" if that's alright.
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 37785231
Yeah, that's totally fine.  Thanks.  I like it when stuff works better that we'd hoped ;-)

Rob.
0
 
LVL 5

Author Comment

by:usslindstrom
ID: 37785365
Just for ref, I ended it making it a little easier on the processor (If anybody references this EE page to accomplish the same sort of task)...

Instead of replacing the image on each pass through, I thew a Variable in the mix that sees if a change is needed.  - Not much of a change, but I'd imagine the little HTA has a tiny bit more breathing room on CPU cycles.  :)

    Sub CheckSpeech
        If SpeechStatus <> objSpeech.Status.RunningState Then
            SpeechStatus = objSpeech.Status.RunningState
            If objSpeech.Status.RunningState = 1 Then
                SP_TextToSpeech.InnerHTML = "<img src=""Images/Button_Spkr_On.gif"" Height=10 Width=13 onclick=""TextToSpeech"" style=""cursor:pointer"" style=""float:right"">"
            Else
                SP_TextToSpeech.InnerHTML = "<img src=""Images/Button_Spkr_Off.gif"" Height=10 Width=13 onclick=""TextToSpeech"" style=""cursor:pointer"" style=""float:right"">"
            End If
        End If
      End Sub

Open in new window

0
 
LVL 65

Expert Comment

by:RobSampson
ID: 37785441
Yep cool.  Good idea.  I set the timer to 500 milliseconds, so if timing is all that critical you could increase that value as well.

Rob.
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

In this post we will learn how to connect and configure Android Device (Smartphone etc.) with Android Studio. After that we will run a simple Hello World Program.
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
An introduction to basic programming syntax in Java by creating a simple program. Viewers can follow the tutorial as they create their first class in Java. Definitions and explanations about each element are given to help prepare viewers for future …
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …

760 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

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now