Charlie Kindschi
Microsoft Corporation
April 3, 1998
Click here to copy the Sound sample discussed in the article below.
Adding various sound cues to events in Microsoft® Office applications can make them easier and more fun to use. Moreover, assigning unique sounds that will play whenever specific command buttons are pressed or specific text boxes are active can actually help increase a user's speed and accuracy. (Note that Office doesn't include an ActiveX® control designed to play sound clips in response to control events.)
This article provides easy step-by-step instructions on how to use a Microsoft Windows® application programming interface (API) function call to add sound cues to events in Office applications. You can use the PlaySound API function to play short sounds or long sounds, and to return control to the user while the sounds are playing. The article concludes with a discussion on programming PlaySound to play sounds in a random order.
If you'd prefer to go straight to the completed sample (workbook) and hear the sound cues in action, skip to the section "Use the Sound.xls workbook" at the end of this article for directions on downloading, setting up, and using the example created by performing the procedures in the article.
There are two main steps involved in employing any Windows API function:
As with any other API function, you must declare the PlaySound function before you can use it. Insert the following declaration in the General Declarations section of any user form class module:
Private Declare Function PlaySound Lib "winmm.dll" _
Alias "PlaySoundA" (ByVal lpszName As String, _
ByVal hModule As Long, ByVal dwFlags As Long) As Long
Note the keyword Private in this declaration. Windows API functions that are declared in a form module must be Private in scope. If you declare the function in a standard module, you can declare the function as Public.
The Long type variable returned by the PlaySound function will be either 1 or 0; 1 indicates success in playing the designated sound, and 0 indicates failure to play the sound. You may find this useful in error-handling code. For example, if a designated sound file is missing or has been corrupted, you might want to notify the user.
Tip If you're using the Office Developer Edition (ODE) or Visual Basic® 5.0, you can find all of the Windows API declaration and constant values in the file Win32API.txt, which is located on your hard disk, or you can download a free copy of this file from the Free Stuff bin on the Office Developer Forum Web site (www.microsoft.com/officedev/o-free.htm).
The default location of Win32API.txt for ODE developers is C:\ Program Files\Microsoft Office\ODETools. If you're using Visual Basic 5.0, consult your documentation or use Windows\Start\Find File or Folders to find Win32API.txt.
Putting the PlaySound function to use is very easy. There are three arguments that must be set for PlaySound to operate:
The following line of code will play a file named "Type.wav," assuming that Type.wav is located in the same folder as the active document:
Call PlaySound("Type.wav", 0, 0)
Note If no flags have been set, PlaySound will try to determine the meaning of its first argument, lpszName. It's better coding practice to specify at least the SND_FILENAME flag. The SND_FILENAME flag tells the PlaySound function that it's dealing with a file rather than a memory address or a system sound. To use a constant with the PlaySound function, or with any other API function, you must first declare the constant in the General Declarations section of the code module that contains the API function declaration. The standard syntax for this is as follows:
Private Const FlagConstant = Value of FlagConstant
Some of the available flags for the flags argument are listed below in a table. You can combine flag values — for example SND_FILENAME and SND_ASYNC — separated by the keyword Or. The SND_ASYNC flag tells the PlaySound function to begin playing the sound and to immediately return control to the user so he or she can continue interacting with the program while the sound plays.
Private Const SND_FILENAME = &H20000 ' Name is a file name.
Private Const SND_ASYNC = &H1 ' Play asyncronously.
Call PlaySound("Type.wav", 0, SND_FILENAME Or SND_ASYNC)
The preferred syntax for calling PlaySound to generate short sound cues is as follows:
Private Const SND_FILENAME = &H20000 ' Name is a file name.
Call PlaySound("Type.wav", 0, SND_FILENAME)
Table 1. Flags you can use with PlaySound
Flag | Value | Description |
SND_SYNC | &H0 | (Default flag) Plays sound synchronously, all the way through. |
SND_ASYNC | &H1 | Plays sound asynchronously. |
SND_RESOURCE | &H4004 | Indicates that the sound is from a resource file. |
SND_FILENAME | &H20000 | Indicates that the sound is a .wav file. |
SND_ALIS_ID | &H10000 | Indicates that the sound is a system sound. This is the ID in the Win.ini file [Sounds]. |
SND_MEMORY | &H4 | Indicates that the sound name resides in memory. |
SND_NOWAIT | &H2000 | Doesn't wait if the sound driver is busy. |
SND_LOOP | &H8 | Continues playing the sound until the function is called again. |
SND_NODEFAULT | &H2 | Doesn't play the default sound (Beep) if the listed sound isn't valid. |
SND_NOSTOP | &H10 | Doesn't stop the current sound. |
In this project, you'll add command buttons and code to a user form in Microsoft Excel and then use those command buttons to play and stop the sounds you've programmed for them. The following series of procedures will work equally well in Microsoft Word, Microsoft Excel, or Microsoft PowerPoint®. The code structures will also work in Microsoft Access, but the procedures used with forms and code modules are slightly different for Access and are not covered in this article.
Private Declare Function PlaySound Lib "winmm.dll" _
Alias "PlaySoundA" (ByVal lpszName As String, _
ByVal hModule As Long, ByVal dwFlags As Long) As Long
Private Const SND_FILENAME = &H20000 ' Name is a file name.
Call PlaySound("C:\Windows\Media\Office97\Type.wav", 0, _
SND_FILENAME)
Adjust the size of your user form, and then align the Play Type Sound button so that your project resembles the illustration following this procedure.
Figure 1. User form with the Play Type Sound button added
Play the sound cue you just programmed
With the code you added in the preceding exercise, you can begin playing short sounds—assuming, of course, that your computer has a working sound system. The operative word in the last sentence is short. The default behavior of the PlaySound function is to take control of the processor and not release it until the sound has stopped playing. This is because the default dwFlags argument of the PlaySound function is SND_SYNC, which tells the function to play a sound all the way through before returning control to the user.
The use of the SND_ASYNC flag to eliminate this problem will be discussed later in this article.
You should hear a clacking sound similar to the sound that an old-style typewriter makes when a key is pressed.
Note If you want more sound files, you need look no further than your Office compact disc. Most of the sounds available for Office are not installed during a Typical setup. To get the rest of the Office sounds, you need the Sounds.exe file, which you'll find in the \Valuepack\Sounds folder on the Office compact disc. Or, if you prefer, you can download this file from the following location on the Web: http://officeupdate.microsoft.com/downloaddetails/sounds.htm. (Registration may be required.) After you've obtained the Sounds.exe file, just double-click it and then follow the setup instructions.
In this section, you'll use the SND_ASYNC flag to augment the simple sound application you've been building so that it will play longer sounds. The SND_ASYNC flag tells the PlaySound function to return control to the user as soon as a sound begins to play.
Private Sub cmdPlayPants_Click()
Call PlaySound("C:\Windows\Media\Office97\Pants.wav", 0, _
SND_FILENAME)
End Sub
Private Sub cmdStopPlay_Click()
Call PlaySound("", 0, 0)
End Sub
You no doubt noticed that clicking the Stop Play button didn't stop the sound.
Figure 2. User form in run view
Playing a longer sound such as Pants.wav makes it easy to see just how pivotal the SND_ASYNC flag can be. Clicking the Stop Play button had no effect because the default action of the PlaySound function is to play synchronously. To remedy this behavior, perform the steps in the following procedure.
Private Const SND_ASYNC = &H1 ' Play asynchronously.
Note Some developers feel that it's good coding practice to declare all the available constants when declaring an API function.
Make the following change to the code in the Click event for the cmdPlayPants button:
Private Sub cmdPlayPants_Click()
Call PlaySound("C:\Windows\Media\Office97\Pants.wav", 0, _
SND_FILENAME Or SND_ASYNC)
End Sub
This time, as you'll notice, clicking Stop Play really does stop the sound.
The code in the Click event for the Stop Play button works by passing an empty string as the first argument of the PlaySound function. The Click event of the cmdStopPlay button can now work to stop playing the sound because control was passed back to the user (meaning the CPU) the moment Pants.wav began to play, thanks to the SND_ASYNC flag.
It's sometimes necessary to simulate a long sound file by playing a short one in a continuous loop. In this procedure, you'll program a command button to simulate the sound of an automobile race.
Const SND_LOOP = &H8 ' Loop the sound until next call.
Private Sub cmdLoopSound_Click()
Call PlaySound("C:\Windows\Media\Office97\Driveby.wav", 0, _
SND_LOOP Or SND_ASYNC)
End Sub
Figure 3. User form with Play Loop Sound button added
As the final phase of this project, you can insulate users from boredom by programming your application to play a variety of different sounds in response to user actions. The code in this procedure will cause the application to randomly play one of three sounds if the Play Random Sound button has been clicked.
Private Sub cmdRandomSound_Click()
' This formula is Int(highest number - lowest number + 1 *
' the random function + 1.
' It will generate a random integer between the upper and ' lower limits set.
' If you add more sounds change the upper limit accordingly.
Dim i As Integer
Randomize
i = Int((3 - 1 + 1) * Rnd + 1)
' Random integer is sent to the PlayThis Function.
Call PlayThis(i)
End Sub
Private Sub PlayThis(Sound As Integer)
Dim strSound As String
Dim strFilePath As String
strFilePath = "C:\Windows\Media\Office97\"
' Use random integer sent by cmdRandomPlay click event
' to set a value for the variable strSound.
Select Case Sound
Case Is = 1
strSound = strFilePath & "pants.wav"
Case Is = 2
strSound = strFilePath & "type.wav"
Case Is = 3
strSound = strFilePath & "driveby.wav"
End Select
' Use the value for the variable strSound as the
' first argument to the PlaySound API function.
Call PlaySound(strSound, 0, SND_FILENAME Or SND_ASYNC)
End Sub
The Randomize statement in the Click event for the cmdRandomSound button "seeds" the RND function with a number from the system timer. The RND function is a built-in Visual Basic function that returns a random number (either 0 or 1) of the variable type Single. The line of code following this paragraph converts this into a random integer from 1 to 3 and places this number in the variable named "i". The range 1 to 3 was used because there are three sound files. If you want to randomize the playing of more than three sound files, adjust this number upward accordingly.
i = Int((3 - 1 + 1) * Rnd + 1)
A random integer from 1 to 3, inclusive, is passed to the function named "PlayThis," where it's used in a Select Case decision block to choose which sound to play. The sound file that's chosen is held in a string variable named "strSound" and is passed to the PlaySound API function.
The project you've just completed is also provided as an Excel workbook that you can download from this Web site. This procedure shows you how to download, open, and use this workbook.