A peek behind the beep

Or rather, a peek behind system sounds.

Windows 3.1 (I think - it might have been Win95) introduced the concept of "application events" to Windows (I prefer to call them system sounds).

But how do these events actually work? It turns out that documentation of how the schema for windows sounds work is relatively hard to find, but it's not very complicated.  This topic in MSDN covers defining application events (I call them system sounds), but it really doesn't describe the schema used to extend them.  This topic also talks about how to register events for your application.  But I'm not aware of any comprehensive description of what it takes to add a sound alias to Windows.

There are 5 steps needed to define a new system sound.  You need to:

  1. Tell Windows about your application.
  2. Tell Windows about the application event (alias) for the sound.
  3. Author the .WAV file for your sound.
  4. Associate your WAV file with your application event
  5. Write your app to call PlaySound

 

I'm not going to go into the authoring thingy, I have no idea how one would go about doing that :).  But I do know how to tell Windows about steps 1, 2, and 4.

To let Windows know about the sound, you need to do two things.  The first is that you need to be sure that PlaySound can figure out what file is associated with the sound, the second is that you need to be able to tell the control panel the "name" of your sound. 

In order to tell PlaySound and the control panel applet about your event, you need to define an "alias" for that event.  Once you've done that, simply insert a call to PlaySound specifying the SND_ALIAS flag, and you're done programming the event (that's #4).  But you still have to plumb in the support to map between the alias and the .WAV file that holds the sound, and that means going to the registry.

 

System sounds live under the "AppEvents\Apps" registry key under HKEY_CURRENT_USER.  From there, you can define the names of your sound aliases, set their display name, and otherwise control how the system manages your sounds.

The Apps key has a pretty straightforward layout:  There are a number of keys under the Apps key, one for each application that's registered to play sounds.

        HKEY_CURRENT_USER\
            AppEvents\
                Schemes\
                    Apps\
                        .Default\
                        MSNMSGR\

The ".Default" key is reserved for use by Windows, nobody should ever add an alias to that section.  Instead, you should create a new key under "Apps" with the filename (no extension) of your executable.  So if Outlook wants to add its own sounds, it should create a key named "Outlook".  The default value for the applications key is the name that the sounds control panel applet will use for the applications section. 

        HKEY_CURRENT_USER\
            AppEvents\
                Schemes\
                    Apps\
                        .Default\
                        MSNMSGR\
                        <APPNAME>\ <default Value "Your app name">

There's a significant drawback to doing this though - you can't support MUI builds (multiple languages on the same machine).  To enable MUI support, you should also create a value with the name DispFileName.  DispFileName should be a REG_SZ formatted as a shell indirect string.  mmsys.cpl will use SHLoadIndirectString to retrieve the actual value in a MUI safe form.  For Vista and beyond, there's a new registry API RegLoadMUIString that lets you do this directly from the registry.  You will also want to specify the SND_APPLICATION flag to PlaySound to tell it to look somewhere other than .Default.  When you specify SND_APPLICATION, PlaySound looks up the currently running executable name and uses that (minus path and extension) for the <appname>

        HKEY_CURRENT_USER\
            AppEvents\
                Schemes\
                    Apps\
                        .Default\
                        MSNMSGR\
                        <APPNAME>\ <default Value "Your app name">
                            VALUE: DispFileName, REG_SZ <value <shell path for your app name>>

Phew, we're almost done.  All we need to do now is to add a the actual sounds.  Under the app specific key, add a new key for each of your sounds - the name of the key matches the name of your alias.  Under the key with the alias, create yet another key named ".Current", the value of that should be either a REG_SZ or a REG_EXPAND_SZ that contains the path of your sound.

        HKEY_CURRENT_USER\
            AppEvents\
                Schemes\
                    Apps\
                        .Default\
                        MSNMSGR\
                        <APPNAME>\ <default Value "Your app name">
                            <Alias Name>\ <default Value: The display name for your alias>
                                .Current <default Value "Path to your .WAV file">

The sounds control panel applet will use the display name specified for your alias.

That's about it - it's a smidge more complicated than the MSDN documentation makes it out to be, but...  Enjoy!

 

 

Btw, if you look at a current XP or Vista machine, you'll find two registry keys under AppEvents, "EventLabels" and "Schemes".  The "EventLabels" key is an alternate mechanism to defines the mapping between the event alias and the display name used for your sound in the control panel.

        HKEY_CURRENT_USER\
            AppEvents\
                EventLabels\
                Schemes

Event Labels define the display name of the event.  It provides a flat list that maps between event aliases and their display names (similar to using the default value for the event listed above).  To add a new display name for a given alias, simply create a key with the name of your alias, and set the default value to the display name for the event.  Once again, for MUI builds, you can use the DispFileName trick to specify a resource that will be used for the name.

        HKEY_CURRENT_USER\
            AppEvents\
                EventLabels\
                    CriticalBatteryAlarm <default value "Critical Battery Alarm">
                        VALUE: DispFileName, REG_SZ <value "@mmsys.cpl,-5827">
                Schemes