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>
&lt;!-- This is the button control  --&gt;

&lt;OBJECT ID="cmdbtn" WIDTH=96 HEIGHT=32
 CLASSID="CLSID:D7053240-CE69-11CD-A777-00DD01143C57"&gt;
    &lt;PARAM NAME="Caption" VALUE="Speak!"&gt;
    &lt;PARAM NAME="Size" VALUE="2540;846"&gt;
    &lt;PARAM NAME="FontCharSet" VALUE="0"&gt;
    &lt;PARAM NAME="FontPitchAndFamily" VALUE="2"&gt;
    &lt;PARAM NAME="ParagraphAlign" VALUE="3"&gt;
    &lt;PARAM NAME="FontWeight" VALUE="0"&gt;
&lt;/OBJECT&gt;

&lt;!-- This is the WavCtl control  --&gt;

&lt;OBJECT 
    CLASSID="clsid:5BB5C4E3-D723-11CF-A521-00A024A652FA"
    WIDTH=1
    HEIGHT=1
    hspace=0
    vspace=0
    ID=WavCtl1 
&gt;
&lt;/OBJECT&gt;

&lt;!-- This is the IETimer control  --&gt;

&lt;OBJECT
    CLASSID="clsid:59ccb4a0-727d-11cf-ac36-00aa00a47dd2"
    id=Timer1
    align=middle
    width=1
    height=1
&gt;
&lt;PARAM NAME="_ExtentX" VALUE="10"&gt;
&lt;PARAM NAME="_ExtentY" VALUE="10"&gt;
&lt;param name="TimeOut" value="100"&gt;
&lt;param name="Enabled" value="True"&gt;
&lt;/OBJECT&gt;

&lt;SCRIPT language="VBScript"&gt;
&lt;!--

'==================================================================
' 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 &lt; 10 Then
        WavCtl1.Play "oh.wav"
        WavCtl1.Play (Mins + 0) & ".wav"

    ' Pronounce a teen digit in its entirety

    ElseIf Mins &lt; 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 &gt;= 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 &lt; 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 &gt;= 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
--&gt;
&lt;/SCRIPT&gt;
</pre>
<hr>

</BODY>
</HTML>