Figure 2 Clock 96FRM
. . .
Attribute VB_Name = "LittleBen"
Attribute VB_Creatable = False
Attribute VB_Exposed = False
Private Declare Function sndPlaySound Lib "winmm.dll" Alias "sndPlaySoundA" (ByVal lpszSoundName As String, ByVal uFlags As Long) As Long
' sndPlaySndSound constants (defined in WINDOWS.H)
Const SND_SYNC = (0)
Const SND_ASYNC = (1)
Const SND_NODEFAULT = (2)
Const SND_MEMORY = (4)
Const SND_LOOP = (8)
Const SND_NOSTOP = (16)
Private Sub PlaySnd(Snd$)
' PlaySnd plays the soundfile named in its argument. By
' default, the .WAV should exist in your home Windows
' directory.
rc% = sndPlaySound(Snd$ + ".WAV", SND_NODEFAULT)
End Sub
Private Sub TimeLbl_Click()
' Whenever the user clicks on the time label, set into
' motion the code for saying the time.
TimeStr$ = Time$
' Get the parsing positions within TimeStr$
Colon1 = InStr(TimeStr$, ":")
Colon2 = InStr(Colon1 + 1, TimeStr$, ":")
Space1 = InStr(Colon2 + 1, TimeStr$, " ")
' Parse the three components. Here, Hrs is taken Mod 12 to avoid
' the 24-hour clock if it exists
Hrs = Val(Left$(TimeStr$, Colon1 - 1)) Mod 12
Mins = Val(Mid$(TimeStr$, Colon1 + 1, 2))
Secs = Val(Mid$(TimeStr$, Colon2 + 1, 2))
If Hrs = 0 Then Hrs = 12
' Pronounce the "it's"
PlaySnd ("its")
' The Hrs is simple - it is a digit between one and twelve, all of
' which exist in separate sound files
PlaySnd (Format$(Hrs, "0"))
' Pronounce the "o'clock" on the hour
If Mins = 0 Then
PlaySnd ("oc")
' Pronounce "oh-mins" if mins is a single digit
ElseIf Mins < 10 Then
PlaySnd ("oh")
PlaySnd (Format$(Mins, "0"))
' Pronounce a teen digit in its entirety
ElseIf Mins < 20 Then
PlaySnd (Format$(Mins, "0"))
' If the Mins are over 20, pronounce the tens part first, followed
' by the ones part. For instance, 34 becomes "thirty" "four"
ElseIf Mins >= 20 Then
PlaySnd (Format$((Mins \ 10) * 10, "00"))
PlaySnd (Format$(Mins Mod 10, "0"))
End If
' Don't pronounce "and zero seconds"
If Secs = 0 Then GoTo Done
' Pronounce your "and" after the minutes
PlaySnd ("and")
' You can just pronounce any number below twenty straight from the file,
' becase you don't need to preface a single digit with an "oh"
If Secs < 20 Then
PlaySnd (Format$(Secs, "0"))
' If there are more than 20 seconds, pronounce it in two chunks, just
' like above for the minutes segment
ElseIf Secs >= 20 Then
PlaySnd (Format$((Secs \ 10) * 10, "00"))
PlaySnd (Format$(Secs Mod 10, "0"))
End If
' Say the closing "second" or "seconds," depending upon the number
' of seconds elapsed
If Secs = 1 Then
PlaySnd ("sec")
Else
PlaySnd ("secs")
End If
Done:
End Sub
Private Sub TimeLbl_DblClick()
' Li'l Ben terminates when you double-click on the label.
End
End Sub
Private Sub Timer1_Timer()
' Every time the Timer goes off (each x/1000 second as
' set as its Interval property), update the caption
' on the TimeLbl label.
TimeLbl.Caption = Time$
End Sub
Figure 3 PLAYSND.OCX
Excerpt from WAVCTRL.H
class CWavctrlCtrl : public COleControl
{
DECLARE_DYNCREATE(CWavctrlCtrl)
// Constructor
public:
CWavctrlCtrl();
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CWavctrlCtrl)
public:
virtual void OnDraw(CDC* pdc, const CRect& rcBounds,
const CRect& rcInvalid);
virtual void DoPropExchange(CPropExchange* pPX);
virtual void OnResetState();
virtual DWORD GetControlFlags();
//}}AFX_VIRTUAL
// Implementation
protected:
. . .
// Dispatch maps
//{{AFX_DISPATCH(CWavctrlCtrl)
afx_msg void Play(LPCTSTR lpWAV);
//}}AFX_DISPATCH
DECLARE_DISPATCH_MAP()
afx_msg void AboutBox();
. . .
// Dispatch and event IDs
public:
enum {
//{{AFX_DISP_ID(CWavctrlCtrl)
dispidPlay = 1L,
//}}AFX_DISP_ID
};
};
Excerpt from WAVCTRLCTL.CPP
// WavctrlCtl.cpp : Implementation of the CWavctrlCtrl OLE control class.
#include "stdafx.h"
#include <mmsystem.h>
#include "wavctrl.h"
#include "WavctrlCtl.h"
#include "WavctrlPpg.h"
. . .
/////////////////////////////////////////////////////////////////////////////
// Dispatch map
BEGIN_DISPATCH_MAP(CWavctrlCtrl, COleControl)
//{{AFX_DISPATCH_MAP(CWavctrlCtrl)
DISP_FUNCTION(CWavctrlCtrl, "Play", Play, VT_EMPTY, VTS_BSTR)
DISP_STOCKPROP_READYSTATE()
//}}AFX_DISPATCH_MAP
DISP_FUNCTION_ID(CWavctrlCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox,
VT_EMPTY, VTS_NONE)
END_DISPATCH_MAP()
. . .
/////////////////////////////////////////////////////////////////////////////
// CWavctrlCtrl::OnDraw - Drawing function
void CWavctrlCtrl::OnDraw(CDC* pdc, const CRect& rcBounds,
const CRect& rcInvalid)
{
if (m_hWnd)
ShowWindow(FALSE);
}
. . .
/////////////////////////////////////////////////////////////////////////////
// CWavctrlCtrl message handlers
void CWavctrlCtrl::Play(LPCTSTR lpWAV)
{
::PlaySound(lpWAV, NULL, SND_FILENAME | SND_SYNC);
}
Figure 4 Clock.htm
<!DOCTYPE HTML PUBLIC "-//W3O//DTD W3 HTML 2.0//EN">
<HTML>
<head>
<title>
VBScript Talking Clock
</title>
</head>
<body>
<STYLE>
HTML {color: white; background: #AAAAFF; margin-left: 8% }
P {font: 11pt/14pt Arial; color: #F6E60A; font-style: bold }
H2 {font: 18pt Arial; color: #730861; font-style: bold }
H2 SPAN { font: 40pt Arial }
BODY {font: 14pt Arial; color:#310c5a; font-style: bold }
PRE {font: 7pt Courier; color:#008800 }
</STYLE>
<h2>
<SPAN>T</SPAN>he <SPAN>T</SPAN>alking <SPAN>C</SPAN>lock<br>
A VBScript demo program written by Joshua Trupin<br>
(c) 1996, Microsoft Corporation
</h2>
<hr>
This demo shows the conversion of an existing Visual Basic program to VBScript.
To do this, the project needed a new (hidden) ActiveX control to play WAV files,
and some minor changes made to string functions. In addition, the problems
with distributing components (such as WAV files) had to be solved through
ActiveX code download services.
<hr>
Here's the clock:
<!-- This is the button control -->
<OBJECT ID="cmdbtn" WIDTH=96 HEIGHT=32
CLASSID="CLSID:D7053240-CE69-11CD-A777-00DD01143C57">
<PARAM NAME="Caption" VALUE="Speak!">
<PARAM NAME="Size" VALUE="2540;846">
<PARAM NAME="FontCharSet" VALUE="0">
<PARAM NAME="FontPitchAndFamily" VALUE="2">
<PARAM NAME="ParagraphAlign" VALUE="3">
<PARAM NAME="FontWeight" VALUE="0">
</OBJECT>
<!-- This is the WavCtl control -->
<OBJECT
CLASSID="clsid:5BB5C4E3-D723-11CF-A521-00A024A652FA"
WIDTH=1
HEIGHT=1
hspace=0
vspace=0
ID=WavCtl1
>
</OBJECT>
<!-- This is the IETimer control -->
<OBJECT
CLASSID="clsid:59ccb4a0-727d-11cf-ac36-00aa00a47dd2"
id=Timer1
align=middle
width=1
height=1
>
<PARAM NAME="_ExtentX" VALUE="10">
<PARAM NAME="_ExtentY" VALUE="10">
<param name="TimeOut" value="100">
<param name="Enabled" value="True">
</OBJECT>
<SCRIPT language="VBScript">
<!--
'==================================================================
' A late change in the IETimer control changed the event name from
' "Timer" to "Time" and the property from "Interval" to "TimeOut"
Sub Timer1_Time
' This is all you need to create a working clock with VBScript
cmdbtn.caption = Time
End Sub
'==================================================================
Sub cmdbtn_Click
' Whenever the user clicks on the time label, set into
' motion the code for saying the time.
' This is a lot easier than the original parsing mechanism
Hrs = Hour(Time)
Mins = Minute(Time)
Secs = Second(Time)
If Hrs = 0 Then Hrs = 12
' Pronounce the "it's"
WavCtl1.Play "its.wav"
' The Hrs is simple - it is a digit between one and twelve, all of
' which exist in separate sound files
WavCtl1.Play (Hrs + 0) & ".wav"
' Pronounce the "o'clock" on the hour
If Mins = 0 Then
WavCtl1.Play "oc.wav"
' Pronounce "oh-mins" if mins is a single digit
ElseIf Mins < 10 Then
WavCtl1.Play "oh.wav"
WavCtl1.Play (Mins + 0) & ".wav"
' Pronounce a teen digit in its entirety
ElseIf Mins < 20 Then
WavCtl1.Play (Mins + 0) & ".wav"
' If the Mins are over 20, pronounce the tens part first, followed
' by the ones part. For instance, 34 becomes "thirty" "four"
ElseIf Mins >= 20 Then
WavCtl1.Play ((Mins \ 10) * 10) & ".wav"
WavCtl1.Play (Mins Mod 10) & ".wav"
End If
' Don't pronounce "and zero seconds"
If Secs = 0 Then Exit Sub
' Pronounce your "and" after the minutes
WavCtl1.Play "and.wav"
' You can just pronounce any number below twenty straight from the file,
' because you don't need to preface a single digit with an "oh"
If Secs < 20 Then
WavCtl1.Play (Secs + 0) & ".wav"
' If there are more than 20 seconds, pronounce it in two chunks, just
' like above for the minutes segment
ElseIf Secs >= 20 Then
WavCtl1.Play ((Secs \ 10) * 10) & ".wav"
WavCtl1.Play (Secs Mod 10) & ".wav"
End If
' Say the closing "second" or "seconds," depending upon the number
' of seconds elapsed
If Secs = 1 Then
WavCtl1.Play "sec.wav"
Else
WavCtl1.Play "secs.wav"
End If
End Sub
-->
</SCRIPT>
(Press the button to hear the clock speak.)
<hr>
Here's the code:
<PRE>
<!-- This is the button control -->
<OBJECT ID="cmdbtn" WIDTH=96 HEIGHT=32
CLASSID="CLSID:D7053240-CE69-11CD-A777-00DD01143C57">
<PARAM NAME="Caption" VALUE="Speak!">
<PARAM NAME="Size" VALUE="2540;846">
<PARAM NAME="FontCharSet" VALUE="0">
<PARAM NAME="FontPitchAndFamily" VALUE="2">
<PARAM NAME="ParagraphAlign" VALUE="3">
<PARAM NAME="FontWeight" VALUE="0">
</OBJECT>
<!-- This is the WavCtl control -->
<OBJECT
CLASSID="clsid:5BB5C4E3-D723-11CF-A521-00A024A652FA"
WIDTH=1
HEIGHT=1
hspace=0
vspace=0
ID=WavCtl1
>
</OBJECT>
<!-- This is the IETimer control -->
<OBJECT
CLASSID="clsid:59ccb4a0-727d-11cf-ac36-00aa00a47dd2"
id=Timer1
align=middle
width=1
height=1
>
<PARAM NAME="_ExtentX" VALUE="10">
<PARAM NAME="_ExtentY" VALUE="10">
<param name="TimeOut" value="100">
<param name="Enabled" value="True">
</OBJECT>
<SCRIPT language="VBScript">
<!--
'==================================================================
' A late change in the IETimer control changed the event name from
' "Timer" to "Time" and the property from "Interval" to "TimeOut"
Sub Timer1_Time
' This is all you need to create a working clock with VBScript
cmdbtn.caption = Time
End Sub
'==================================================================
Sub cmdbtn_Click
' Whenever the user clicks on the time label, set into
' motion the code for saying the time.
' This is a lot easier than the original parsing mechanism
Hrs = Hour(Time)
Mins = Minute(Time)
Secs = Second(Time)
If Hrs = 0 Then Hrs = 12
' Pronounce the "it's"
WavCtl1.Play "its.wav"
' The Hrs is simple - it is a digit between one and twelve, all of
' which exist in separate sound files
WavCtl1.Play (Hrs + 0) & ".wav"
' Pronounce the "o'clock" on the hour
If Mins = 0 Then
WavCtl1.Play "oc.wav"
' Pronounce "oh-mins" if mins is a single digit
ElseIf Mins < 10 Then
WavCtl1.Play "oh.wav"
WavCtl1.Play (Mins + 0) & ".wav"
' Pronounce a teen digit in its entirety
ElseIf Mins < 20 Then
WavCtl1.Play (Mins + 0) & ".wav"
' If the Mins are over 20, pronounce the tens part first, followed
' by the ones part. For instance, 34 becomes "thirty" "four"
ElseIf Mins >= 20 Then
WavCtl1.Play ((Mins \ 10) * 10) & ".wav"
WavCtl1.Play (Mins Mod 10) & ".wav"
End If
' Don't pronounce "and zero seconds"
If Secs = 0 Then Exit Sub
' Pronounce your "and" after the minutes
WavCtl1.Play "and.wav"
' You can just pronounce any number below twenty straight from the file,
' because you don't need to preface a single digit with an "oh"
If Secs < 20 Then
WavCtl1.Play (Secs + 0) & ".wav"
' If there are more than 20 seconds, pronounce it in two chunks, just
' like above for the minutes segment
ElseIf Secs >= 20 Then
WavCtl1.Play ((Secs \ 10) * 10) & ".wav"
WavCtl1.Play (Secs Mod 10) & ".wav"
End If
' Say the closing "second" or "seconds," depending upon the number
' of seconds elapsed
If Secs = 1 Then
WavCtl1.Play "sec.wav"
Else
WavCtl1.Play "secs.wav"
End If
End Sub
-->
</SCRIPT>
</pre>
<hr>
</BODY>
</HTML>