Adding a sound to the Alt+Tab window


Today's Little Program plays a sound when the Alt+Tab window appears and disappears.

#define STRICT
#include <windows.h>
#include <mmsystem.h>

HWND g_hwndAltTab = nullptr;

void CALLBACK WinEventProc(
    HWINEVENTHOOK hWinEventHook,
    DWORD event,
    HWND hwnd,
    LONG idObject,
    LONG idChild,
    DWORD dwEventThread,
    DWORD dwmsEventTime
)
{
 PCTSTR pszSound = nullptr;
 switch (event) {
 case EVENT_SYSTEM_SWITCHSTART:
  if (!g_hwndAltTab) {
   g_hwndAltTab = hwnd;
   pszSound = "C:\\Windows\\Media\\Speech on.wav";
  }
  break;
 case EVENT_SYSTEM_SWITCHEND:
  if (g_hwndAltTab) {
   g_hwndAltTab = nullptr;
   pszSound = "C:\\Windows\\Media\\Speech sleep.wav";
  }
  break;
 }
 if (pszSound) {
  PlaySound(pszSound, nullptr, SND_FILENAME | SND_ASYNC);
 }
}

int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev,
                   LPSTR lpCmdLine, int nShowCmd)
{
 HWINEVENTHOOK hWinEventHook = SetWinEventHook(
     EVENT_SYSTEM_SWITCHSTART, EVENT_SYSTEM_SWITCHEND,
     nullptr, WinEventProc, 0, 0,
     WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);

 if (hWinEventHook) {
  MessageBox(nullptr, "Close this window when sufficiently annoyed.",
             "Hello", MB_OK);
  UnhookWinEvent(hWinEventHook);
 }
 return 0;
}

The program registers an accessibility event hook for the EVENT_SYSTEM_SWITCH­START and EVENT_SYSTEM_SWITCH­END events. The Start event fires when an Alt+Tab operation begins, and the End event fires when an Alt+Tab operation completes. As noted in the documentation, you can get spurious End events, so we keep track of our current state to avoid any surprises.

In addition to adding an annoying sound to the Alt+Tab window, let's also add an annoying sound each time you move focus to a new item.

HWINEVENT g_hWinEventHookFocus = nullptr;

void CALLBACK WinEventProc(
    HWINEVENTHOOK hWinEventHook,
    DWORD event,
    HWND hwnd,
    LONG idObject,
    LONG idChild,
    DWORD dwEventThread,
    DWORD dwmsEventTime
)
{
 PCTSTR pszSound = nullptr;
 switch (event) {
 case EVENT_SYSTEM_SWITCHSTART:
  if (!g_hwndAltTab) {
   g_hwndAltTab = hwnd;
   g_hWinEventHookFocus = SetWinEventHook(
     EVENT_OBJECT_FOCUS, EVENT_OBJECT_FOCUS,
     NULL, WinEventProc, 0, 0,
     WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);
   pszSound = "C:\\Windows\\Media\\Speech on.wav";
  }
  break;
 case EVENT_SYSTEM_SWITCHEND:
  if (g_hwndAltTab) {
   g_hwndAltTab = nullptr;
   UnhookWinEvent(g_hWinEventHookFocus);
   g_hWinEventHookFocus = nullptr;
   pszSound = "C:\\Windows\\Media\\Speech sleep.wav";
  }
  break;
 case EVENT_OBJECT_FOCUS:
  if (hwnd == g_hwndAltTab) {
   pszSound = TEXT("C:\\Windows\\Media\\Speech Misrecognition.wav");
  }
  break;
 }
 if (pszSound) {
  PlaySound(pszSound, nullptr, SND_FILENAME | SND_ASYNC);
 }
}

int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev,
                   LPSTR lpCmdLine, int nShowCmd)
{
 HWINEVENTHOOK hWinEventHook = SetWinEventHook(
     EVENT_SYSTEM_SWITCHSTART, EVENT_SYSTEM_SWITCHEND,
     nullptr, WinEventProc, 0, 0,
     WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);

 if (hWinEventHook) {
  MessageBox(nullptr, "Close this window when sufficiently annoyed.",
             "Hello", MB_OK);
  UnhookWinEvent(hWinEventHook);
  if (g_hWinEventHookFocus) {
   UnhookWinEvent(g_hWinEventHookSelect);
  }
 }
 return 0;
}

Okay, this was a pretty annoying program, but maybe you can use it for something better.

Comments (17)
  1. Brian_EE says:

    Step 1: Dispense with the window.

    Step 2: Pick more amusing audio samples.

    Step 3: Wait for that annoying coworker to leave his/her computer unlocked.

    Step 4: Drop this into his/her startup folder.

  2. Charles says:

    @Brian

    Now if only the PC Speaker was still accessible.

  3. Boris says:

    @Brian: but surely your prank relies on the coworker using ALT-TAB on a regular basis? I never use it and only tested it after reading this article. Conclusion: I can't use it comfortably since I have way too many minimized windows, and besides, it is much easier to place the mouse cursor over an application icon in the Windows 7 taskbar.

  4. How to get started with little program says:

    I see Raymond reference the scratch program and programs like this often, but don't know how I might dig into them myself. What do I need to have to use this code?  Visual Studio I assume?

  5. Crescens2k says:

    @How to get started with little program:

    Well, Visual Studio will have the stuff needed out of the box. MinGW should also come with the right things to link with the Windows API. Just be warned that because C++ compilers that don't rely on the Windows SDK are community driven, then they may not be up to date with API exports.

    If you are not a C++ user, then you may be able to dig into these using language capabilities. .NET languages, for example, have a pretty large library and the ability to access native code via platform invoke. Other languages have similar mechanisms and may be able to call directly into the Windows API if there is no direct language/library support for what is needed.

  6. Evan says:

    @How to get started with little program:

    Also note, if you don't already know, that there's a free version (the 'Express Edition') of Visual Studio. So if you're thinking it'll probably cost $$$, you can get away without.

  7. Muzer_ says:

    @Boris Alt+Escape (and alt+shift+escape) is quite good for skipping minimised windows.

  8. Mc says:

    Also combine this with my little program to randomly eject the user's CD tray every few hours.    Much hilarity ensues  (in our office anyway).

  9. GregM says:

    "Also combine this with my little program to randomly eject the user's CD tray every few hours. "

    I'm glad that I use a slot-load DVD drive.  :)

  10. > Now if only the PC Speaker was still accessible.

    In that case, that's the way to emulate a Hollywood GUI, where *anything* you do does some kind of beep.

  11. Josh says:

    Minor nitpick: The string literals used in the first example aren't wrapper in TEXT(), so this wouldn't work when compiled for Unicode. The literal added to example #2 is correctly wrapped though.

  12. Colin says:

    The string literals are not loaded from a resource either.  You're missing the point.

  13. Boris says:

    Do I detect a Fantastic Four reference in the name of the first WAV?

  14. PacMani says:

    My computer does this by default. The shielding of my graphics / sound card is so bad I can hear everything which animates or gets moved – like in CSI Miami.

  15. Brian_EE says:

    @Josh: "Remember, Little Programs do little or no error checking." blogs.msdn.com/…/10490951.aspx

  16. 12BitSlab says:

    Besides some of the fun things that can be done with the stuff Raymond presented, I have noticed over the years that his employer does more to allow developers to make their code accessible to those with physical challenges than just about anyone else who markets a commercial OS.  This is near and dear to my heart since I fit into that category.

  17. amroamroamro says:

    @How to get started with little program:

    In addition to VS Express Edition, you can also download a MinGW distribution (TDM-GCC is a good one). Copy/paste the above code, and compile with:

    g++ -std=c++11 -mwindows -o alttab.exe alttab.cpp -lwinmm

Comments are closed.