Windows Forms classes are bereft of a simple way to play sounds. This glaring oversight is however easily rectified with a little bit of platform-invoke interop.
There are a couple of ways to do this. The first method requires the multimedia API sndPlaySnd and a few constants defined but once this is done you can add sounds to your Windows Forms applications easily. This API is a subset of the PlaySound API which can also be accessed through interop.
First you need to import the sndPlaySound or PlaySound API from the multimedia DLL. Interop enables us to import these signatures in a number of ways. For example, in some configurations the sndPlaySound method can be passed the address of a .WAV sound stored in memory but C# and VB are a bit finicky about casting strings to pointers so we can overload the p/invoke import statement to provide a version of the method signature that accepts an IntPtr instead of a string.
static extern int sndPlaySound(string lpszSound, int fuSound);
static extern int sndPlaySound(IntPtr ptr, int fuSound);
Shared Function sndPlaySound(lpszSound As String, fuSound As Integer) As Integer
Shared Function sndPlaySound(ptr As IntPtr, fuSound As Integer) As Integer
The constants required for the multimedia functions can be converted from the old C++ header files.
SND_SYNC = 0x0000, /* play synchronously (default) */
SND_ASYNC = 0x0001, /* play asynchronously */
SND_NODEFAULT = 0x0002, /* silence (!default) if sound not found */
SND_MEMORY = 0x0004, /* pszSound points to a memory file */
SND_LOOP = 0x0008, /* loop the sound until next sndPlaySound */
SND_NOSTOP = 0x0010, /* don't stop any currently playing sound */
SND_NOWAIT = 0x00002000, /* don't wait if the driver is busy */
SND_ALIAS = 0x00010000, /* name is a registry alias */
SND_ALIAS_ID = 0x00110000, /* alias is a predefined ID */
SND_FILENAME = 0x00020000, /* name is file name */
SND_RESOURCE = 0x00040004, /* name is resource name or atom */
SND_PURGE = 0x0040, /* purge non-static events for task */
SND_APPLICATION = 0x0080, /* look for application specific association */
SND_SYNC = &H0 ' play synchronously (default)
SND_ASYNC = &H1 ' play asynchronously
SND_NODEFAULT = &H2 ' silence (!default) if sound not found
SND_MEMORY = &H4 ' pszSound points to a memory file
SND_LOOP = &H8 ' loop the sound until next sndPlaySound
SND_NOSTOP = &H10 ' don't stop any currently playing sound
SND_NOWAIT = &H2000 ' don't wait if the driver is busy
SND_ALIAS = &H10000 ' name is a registry alias
SND_ALIAS_ID = &H110000 ' alias is a predefined ID
SND_FILENAME = &H20000 ' name is file name
SND_RESOURCE = &H40004 ' name is resource name or atom
SND_PURGE = &H40 ' purge non-static events for task
SND_APPLICATION = &H80 ' look for application specific association
End Enum 'soundConstants
Then, to play a sound simply call the method and provide the sound file.
You can embed a .wav file into your application by adding it to the application and then setting the build action to "embedded resource" in the solution item properties. This enables you to ship an application with the sounds built into the resources and so there are no extra files to distribute.
Getting at the file is a little more complex than simply nominating the filename an must be done using a Garbage Collector handle (GCHandle) and a pinned array. The following listing assumes a file has been embedded in the resources and is accessible as a stream.
byte buffer=new byte[s.Length];
Dim s As Stream = Me.GetType().Assembly.
Dim buffer(s.Length) As Byte
s.Read(buffer, 0, CInt(s.Length))
Dim h As GCHandle = GCHandle.Alloc(buffer)
Dim ptr As IntPtr = Marshal.
- // Include file
- #include "mmsystem.h"
- // Link to this library
- #pragma comment( lib, "winmm.
- int main( int argc, char **
- // Will block till the
whole file is played, use SND_ ASYNC to play asynchronously
- sndPlaySound( "c://
windows//media//ding.wav", SND_SYNC );
- // Play for ever, should
- sndPlaySound( "c://
windows//media//ding.wav", SND_ASYNC|SND_LOOP );
- // Sleep for 5 seconds
- Sleep( 5000 );
- // Enough is enough stop
making that stupid noise
- sndPlaySound( NULL, SND_
- return 0;
- }// End main