How to Detect Special Key Presses in a Notebook?

Following detects backspace on Mac:

SetOptions[EvaluationNotebook[],NotebookEventActions->
     {{"KeyDown","\.08"}:>Print["triggered"]}]

This code can be helpful for finding out different codes for non-standard keys.

SetOptions[EvaluationNotebook[],NotebookEventActions->
     {"KeyDown":>Print[FullForm@CurrentValue["EventKey"]]}]

@BlacKow's answer works well on Mac, but Mathematica cannot handle special keys (s.a. F2 or PAUSE) on Windows. Thus,

Here is a Windows workaround:

The idea is to create a dynamic link library that runs in a separate thread, as explained here. In this separate thread, the keyboard status is continuously tested. Once the specified key is pressed, an event is raised to the MMA kernel. The following code requires a working C-compiler on a Windows PC:

Needs["CCompilerDriver`GenericCCompiler`"];

keyListen[keycode_, action_] := With[{
    libMain = First@FileNames["async-examples-libmain.c", {$InstallationDirectory}, Infinity],
    src = "
      #include <stdlib.h>
      #include \"WolframLibrary.h\"
      #include \"WolframCompileLibrary.h\"
      #include \"WolframStreamsLibrary.h\"
      #include \"windows.h\"                    // for GetAsyncKeyState()

      /**********************************************************/
      typedef struct keyTrackerArgs_st
      {
          WolframIOLibrary_Functions ioLibrary;
          mint key;
      }* keyTrackerArgs;

      static void key_tracker(mint asyncObjID, void* vtarg)
      {
          keyTrackerArgs targ = (keyTrackerArgs)vtarg;
          WolframIOLibrary_Functions ioLibrary = targ->ioLibrary;
          const mint key = targ->key;
          free(targ);

          while(ioLibrary->asynchronousTaskAliveQ(asyncObjID))
          {
              if(GetAsyncKeyState(key) & 0x0001) {
                  ioLibrary->raiseAsyncEvent(asyncObjID, \"KeyPress\", NULL);
              }
          }
      }

      DLLEXPORT int start_key_tracker(WolframLibraryData libData,
          mint Argc, MArgument *Args, MArgument Res) 
      {
          mint asyncObjID;
          WolframIOLibrary_Functions ioLibrary = libData->ioLibraryFunctions;
          keyTrackerArgs threadArg = (keyTrackerArgs)malloc(sizeof(struct keyTrackerArgs_st));

          if(Argc != 1)
              return LIBRARY_FUNCTION_ERROR;

          threadArg->ioLibrary = ioLibrary;
          threadArg->key = MArgument_getInteger(Args[0]);
          asyncObjID = ioLibrary->createAsynchronousTaskWithThread(key_tracker, threadArg);
          MArgument_setInteger(Res, asyncObjID);

          return LIBRARY_NO_ERROR;
      }
      "
  },
  Module[{srcFile},
    srcFile = CreateFile["src.c"];
    WriteString[srcFile, src];
    Close[srcFile];
    lib = CreateLibrary[{srcFile, libMain}, "keyLib", "IncludeDirectories" -> {DirectoryName[libMain]}];
    DeleteFile[srcFile];
    keyListener = LibraryFunctionLoad[lib, "start_key_tracker", {Integer}, Integer];
    Internal`CreateAsynchronousTask[keyListener, {keycode}, action];
  ]
]

Let's say we want to make a sound (Beep[]) every time the "PAUSE" key is hit. Then we evaluate

keyListen[19, Beep[] &]

where 19 is the code for "VK_PAUSE". Here are all the Windows key codes, in case you need them:

virtualKeyList = {"VK_LBUTTON" -> 1, "VK_RBUTTON" -> 2, 
   "VK_CANCEL" -> 3, "VK_MBUTTON" -> 4, "VK_XBUTTON1" -> 5, 
   "VK_XBUTTON2" -> 6, "VK_BACK" -> 8, "VK_TAB" -> 9, 
   "VK_CLEAR" -> 12, "VK_RETURN" -> 13, "VK_SHIFT" -> 16, 
   "VK_CONTROL" -> 17, "VK_MENU" -> 18, "VK_PAUSE" -> 19, 
   "VK_CAPITAL" -> 20, "VK_KANA" -> 21, "VK_HANGUEL" -> 21, 
   "VK_HANGUL" -> 21, "VK_JUNJA" -> 23, "VK_FINAL" -> 24, 
   "VK_HANJA" -> 25, "VK_KANJI" -> 25, "VK_ESCAPE" -> 27, 
   "VK_CONVERT" -> 28, "VK_NONCONVERT" -> 29, "VK_ACCEPT" -> 30, 
   "VK_MODECHANGE" -> 31, "VK_SPACE" -> 32, "VK_PRIOR" -> 33, 
   "VK_NEXT" -> 34, "VK_END" -> 35, "VK_HOME" -> 36, "VK_LEFT" -> 37, 
   "VK_UP" -> 38, "VK_RIGHT" -> 39, "VK_DOWN" -> 40, 
   "VK_SELECT" -> 41, "VK_PRINT" -> 42, "VK_EXECUTE" -> 43, 
   "VK_SNAPSHOT" -> 44, "VK_INSERT" -> 45, "VK_DELETE" -> 46, 
   "VK_HELP" -> 47, "VK_LWIN" -> 91, "VK_RWIN" -> 92, "VK_APPS" -> 93,
    "VK_SLEEP" -> 95, "VK_NUMPAD0" -> 96, "VK_NUMPAD1" -> 97, 
   "VK_NUMPAD2" -> 98, "VK_NUMPAD3" -> 99, "VK_NUMPAD4" -> 100, 
   "VK_NUMPAD5" -> 101, "VK_NUMPAD6" -> 102, "VK_NUMPAD7" -> 103, 
   "VK_NUMPAD8" -> 104, "VK_NUMPAD9" -> 105, "VK_MULTIPLY" -> 106, 
   "VK_ADD" -> 107, "VK_SEPARATOR" -> 108, "VK_SUBTRACT" -> 109, 
   "VK_DECIMAL" -> 110, "VK_DIVIDE" -> 111, "VK_F1" -> 112, 
   "VK_F2" -> 113, "VK_F3" -> 114, "VK_F4" -> 115, "VK_F5" -> 116, 
   "VK_F6" -> 117, "VK_F7" -> 118, "VK_F8" -> 119, "VK_F9" -> 120, 
   "VK_F10" -> 121, "VK_F11" -> 122, "VK_F12" -> 123, "VK_F13" -> 124,
    "VK_F14" -> 125, "VK_F15" -> 126, "VK_F16" -> 127, 
   "VK_F17" -> 128, "VK_F18" -> 129, "VK_F19" -> 130, "VK_F20" -> 131,
    "VK_F21" -> 132, "VK_F22" -> 133, "VK_F23" -> 134, 
   "VK_F24" -> 135, "VK_NUMLOCK" -> 144, "VK_SCROLL" -> 145, 
   "VK_OEM_PLUS" -> 187, "VK_OEM_COMMA" -> 188, "VK_OEM_MINUS" -> 189,
    "VK_OEM_PERIOD" -> 190, "VK_OEM_2" -> 191, "VK_OEM_5" -> 220, 
   "VK_OEM_8" -> 223, "VK_PACKET" -> 231};

So after BlacKow's insight I found more of these by playing with this:

EventHandler[
 Panel["", ImageSize -> 100],
 "KeyDown" :>
  Print[Row@{FullForm@CurrentValue@"EventKey", " pressed"}]
 ]

A few more points of interest (this is potentially Mac specific as I am a Mac user):

"\[RawEscape]" is the escape key

"\.1c" is "LeftArrowKeyDown"

"\.1e" is "UpArrowKeyDown"

"\.1d" is "RightArrowKeyDown"

"\.1f" is "DownArrowKeyDown"

"\r" is "ReturnKeyDown"

"\[GreaterEqual]" is control-. (and various other special characters can be found as a control-key combo, but these can be easily figured out I think)

"\.10" is function-(any function key not bound)

Hopefully someone can extend this further and to Windows / Linux? Useful collection of keys to have out there.