Recipe 12.1 Play an Embedded Sound File from Within an Application

12.1.1 Problem

Your application stores WAV files as OLE objects within a table, and you'd like to be able to play them on demand. You know that users can double-click on the icon in a form to play the sounds, but you'd like some control over this. Is there a way to play one of these embedded sounds when you need to?

12.1.2 Solution

Access gives you substantial control over the use of OLE objects. Using the Action property of the control that's displaying the OLE object, you can tell the object to activate itself, copy itself to or paste itself from the Windows clipboard, update its data, and close or delete itself. The Action property can be used for bound or unbound OLE objects and graphs, too. You can also call up the Insert Object or Paste Special dialog to place data into the control. This solution uses a bound OLE field, but it works just as well with an unbound object on a form.

Load and run frmOLE (shown in Figure 12-1) from 12-01.MDB. This is a continuous form, pulling the data from the table tblOLE. If you click on an Activate button, the form activates that OLE object, which is stored in the OLEObject field of the table. The sample table includes a few WAV files, one Microsoft Graph object, and a MIDI file. Clicking on the Activate button will either play the sound or activate Microsoft Graph so you can edit the tiny graph object. Click on the Insert button to call up the Insert Object dialog, which allows you to insert any OLE object you like into the table. Click on the Open button to open the object in its own editing window rather than activating it in place.

Figure 12-1. frmOLE allows you to play or insert OLE objects

Follow these simple steps to create such a form:

  1. Create a new table or modify an existing table, adding a column (named OLEObject in the sample) with its Data Type set to OLE object. Note that you cannot index on an OLE field, and therefore it can't be your primary key for the table.

  2. Create a new form. To emulate the sample form, the only property you need to set is the DefaultView property. Set it to Continuous Forms so that you'll see multiple rows at the same time. This isn't necessary, but it will make your form look like the sample.

  3. Create a bound OLE object (the cactus picture with the XYZ across the top on the toolbar) on the form. The code in this example is based on a control named objOLE; adjust the code appropriately if you name your control something else. The sample form includes the description field from tblOLE as a text box, but this isn't used in the sample code.

  4. Add three buttons: cmdOpen, cmdActivate, and cmdInsert, with captions Open, Activate, and Insert, respectively. Attach the following code to the Activate button's Click event (see the Preface for more information on creating event procedures):

    Private Sub cmdActivate_Click( )
       Dim ctl As Control
       On Error Resume Next
       Set ctl = Me.objOLE
       ctl.Verb = acOLEVerbPrimary
       ctl.Action = acOLEActivate
    End Sub 
    Attach the following code to the Insert button's Click event:
    Private Sub cmdInsert_Click( )
       On Error Resume Next
       Me.objOLE.Action = acOLEInsertObjDlg
    End Sub

    Attach the following code to the Open button's Click event:

    Private Sub cmdOpen_Click( )
       Dim ctl As Control
       On Error Resume Next
       Set ctl = Me.objOLE
       ' Open, rather than just activate in place.
       ctl.Verb = acOLEVerbOpen
       ctl.Action = acOLEActivate
    End Sub
  5. Save your form and run it. When you click on the Insert button, you'll see the Insert Object dialog (Figure 12-2). This dialog allows you to create a new object or to insert one from an existing file. Once you make your choice, Access places the object into the table and displays it on the form. When you want to activate the object, click on the Activate button. For a WAV or MIDI file, this causes your sound to play; for a Microsoft Graph object, it activates Microsoft Graph. To open an editing window for the object, click on the Open button.

Figure 12-2. The Insert Object dialog

12.1.3 Discussion

The Action property for OLE objects in Access is different from almost any other property, in that setting its value causes an action to take place. Normally, properties describe characteristics of an object, and methods cause actions to take place. In this case, however, when you set the Action property to the constant acOLEActivate, Access activates the control at the time you set the property. If you set the Action property to the constant acOLEInsertObjDlg, Access displays the modal Insert Object dialog at the time you change the property. By changing the OLE control's Action property, the code tells Access what action to take at that point. By changing the Verb property from acOleVerbPrimary (to activate the object) to acOleVerbOpen, you control how the object is opened: in place, or in its own window.

Table 12-1 lists the values that you're likely to use for the Action property. Others are available, but this list will get you started. For more information, see the online help topics on the Action and Verb properties.

Table 12-1. Possible values of the Action property






Same as choosing the Edit Copy menu item. Copies the OLE object onto the Windows clipboard.



Same as choosing the Edit Paste menu item. Pastes the OLE object from the Windows clipboard into your control.



Retrieves the most current data for the OLE object from the application that created it and displays it as a graphic.



Same as double-clicking the control. You must set the control's Verb property before you can use this Action.



Closes the OLE object and ends the active connection with the application that provided the object.



Displays the Insert Object modal dialog, allowing the user to insert an object.

This technique works just as well for unbound objects on forms. For example, if you have an embedded Word document, you could use code to activate the OLE object (named Embedded0 in the following example), set its first paragraph to bold, and then close the object:

Dim objWord As Object
' Activate the OLE object, using the primary verb.
Me.Embedded0.Verb = acOLEVerbPrimary
Me.Embedded0.Action = acOLEActivate
Set objWord = Me.Embedded0.Object.Application.WordBasic

objWord.ParaDown 1, 1
objWord.Bold 1
Set objWord = Nothing
' Close the OLE object.
Me.Embedded0.Action = acOLEClose

By the way, if you need to play a WAV file but don't want to embed an OLE object or use OLE at all, you can use the Windows API sndPlaySound function to do your work. (This function is aliased as acb_apiSndPlaySound in 12-01.MDB.) Just insert the following declarations and constants in a form's module:

Private Declare Function sndPlaySound Lib "winmm.dll" _
 Alias "sndPlaySoundA" (ByVal lpszSoundName As String, _
 ByVal uFlags As Long) As Long
Private Const SND_SYNC = &H0
Private Const SND_ASYNC = &H1
Private Const SND_NODEFAULT = &H2
Private Const SND_LOOP = &H8
Private Const SND_NOSTOP = &H10

Table 12-2 describes the possible flag values for the sndPlaySound function call.

Table 12-2. Possible values for the intFlags parameter to sndPlaySound






Plays the sound synchronously and does not return from the function until the sound ends.



Plays the sound asynchronously and returns from the function immediately after beginning the sound. To terminate a sound once it's started, call acb_apiSndPlaySound, passing vbNullChar as the first parameter.



Doesn't play the default sound if the requested sound can't be found.



The sound continues to play repeatedly until you call acb_apiSndPlaySound with the first parameter set to vbNullChar. You must also specify the SND_ASYNC flag to loop sounds.



Returns immediately with a value of FALSE without playing the requested sound if a sound is currently playing.

Normally, you'll call the sndPlaySound function to play the WAV file. If you use the SND_ASYNC or SND_LOOP flags, you'll need to call the sndPlaySound function again, passing the vbNullChar constant as the first parameter. The following code example is the simplest way to play a WAV file using the Windows API. You can try this out by loading the form frmSndPlaySound from 12-01.MDB and pressing the button on the form, which executes the following code:

Private Sub Button0_Click( )
   Dim varSound As Variant
   Dim intFlags As Integer
   Dim intResult As Integer
   Dim strWinDir As String
   Dim intCount As Integer

   Const conMaxLen = 255

   ' Find the Windows directory.
   strWinDir = Space(conMaxLen)
   intCount = GetWindowsDirectory(strWinDir, conMaxLen)
   strWinDir = Left(strWinDir, intCount)
   ' Get the file name, using the common file open dialog.
   varSound = acbCommonFileOpenSave(InitialDir:=strWinDir, _
    Filter:=acbAddFilterItem("", "WAV Files", "*.WAV"), _
    DialogTitle:="Choose a WAV File")
   If Not IsNull(varSound) Then
      intResult = sndPlaySound(varSound, intFlags)
      If intResult = 0 Then
         MsgBox "Unable to play sound."
      End If
   End If
End Sub

This example is complicated by the fact that it uses the Windows File Open dialog to request the name of the WAV file that you'd like to play (the folder named Media is a good place to look), but the heart of the routine is quite simple.

12.1.4 See Also

For more information on working with the Windows API, see Chapter 11.