Il Framework .NET non fornisce metodi che consentono di 
registrare HotKey a livello di sistema. In questo caso ci viene 
in aiuto il Platform Invoke:
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Windows.Forms;
namespace HotKey
{
    public class HotKeyHandler : NativeWindow, IDisposable
    {
        #region Platform Invoke
        [Flags]
        public enum Modifiers
        {
            NONE = 0,
            MOD_ALT = 0x01,
            MOD_CONTROL = 0x02,
            MOD_SHIFT = 0x04,
            MOD_WIN = 0x08
        }
        private static readonly int WM_HOTKEY = 0x0312;
        [DllImport("user32.dll")] private static extern bool RegisterHotKey(IntPtr hWnd, int Id, int fsModifiers, int vlc);
        [DllImport("user32.dll")] private static extern bool UnregisterHotKey(IntPtr hWnd, int Id);
        #endregion
        private struct HotKeyInfo
        {
            public Keys Key;
            public Modifiers Modifier;
            public HotKeyInfo(Keys Key, Modifiers Modifier)
            {
                this.Key = Key;
                this.Modifier = Modifier;
            }
            public static bool operator==(HotKeyInfo HotKey1, HotKeyInfo HotKey2)
            {
                return ((HotKey1.Key == HotKey2.Key) && (HotKey1.Modifier == HotKey2.Modifier));
            }
            public static bool operator !=(HotKeyInfo HotKey1, HotKeyInfo HotKey2)
            {
                return ((HotKey1.Key != HotKey2.Key) || (HotKey1.Modifier != HotKey2.Modifier));
            }
            public override bool Equals(object obj)
            {
                if (obj == null || GetType() != obj.GetType())
                    return false;
                return this == (HotKeyInfo)obj;
            }
            public override int GetHashCode()
            {
                return base.GetHashCode();
            }
        }
        private static int mLastID = 0;
        private Dictionary<int, HotKeyInfo> mHotKeys = null;
        public HotKeyHandler()
        {
            this.CreateHandle(new CreateParams());
            mHotKeys = new Dictionary<int, HotKeyInfo>();
        }
        public bool Register(Keys Key)
        {
            return this.Register(Key, Modifiers.NONE);
        }
        public bool Register(Keys Key, Modifiers Modifier)
        {
            mLastID++;
            //Registra la HotKey.
            if (RegisterHotKey(this.Handle, mLastID, (int)Modifier, (int)Key) == true)
            {
                //Se la registrazione ha avuto esito positivo, aggiunge la hotkey all'hashtable.
                //Questo serve per sapere quale hotkey è stata premuta, nel caso in cui ne
                //siano state registrate più di una.
                mHotKeys.Add(mLastID, new HotKeyInfo(Key, Modifier));
                return true;
            }
            return false;
        }
        public void Unregister(Keys Key, Modifiers Modifier)
        {
            HotKeyInfo hotKey = new HotKeyInfo(Key, Modifier);
            if (mHotKeys.ContainsValue(hotKey))
            {
                foreach (int ID in mHotKeys.Keys)
                {
                    if (mHotKeys[ID] == hotKey)
                    {
                        UnregisterHotKey(this.Handle, ID);
                        mHotKeys.Remove(ID);
                        return;
                    }
                }
            }
        }
        public void Unregister()
        {
            foreach (int ID in mHotKeys.Keys)
                UnregisterHotKey(this.Handle, ID);
           
            mHotKeys.Clear();
            mLastID = 0;
        }
        #region Dispose
        private void FreeResources()
        {
            try
            {
                this.Unregister();
                if (this.Handle != IntPtr.Zero)
                    this.DestroyHandle();
            }
            catch { }
        }
        ~HotKeyHandler()
        {
            this.FreeResources();
        }
        public void Dispose()
        {
            this.FreeResources();
            GC.SuppressFinalize(this);
        }
        #endregion
        public delegate void HotKeyPressedEventHandler(object sender, HotKeyPressedEventArgs e);
        //Evento che viene generato quando si preme una HotKey.
        public event HotKeyPressedEventHandler HotKeyPressed;
        protected override void WndProc(ref System.Windows.Forms.Message m)
        {
            if (m.Msg == HotKeyHandler.WM_HOTKEY)
            {
                //hID contiene l'ID della HotKey premuta.
                int hID = m.WParam.ToInt32();
                if (mHotKeys.ContainsKey(hID))
                {
                    if (this.HotKeyPressed != null)
                        this.HotKeyPressed(this, new HotKeyPressedEventArgs(mHotKeys[hID].Key, mHotKeys[hID].Modifier));
                    else
                        base.WndProc(ref m);
                }
                else
                {
                    base.WndProc(ref m);
                }
            }
            else
            {
                base.WndProc(ref m);
            }
        }
    }
    public class HotKeyPressedEventArgs : EventArgs
    {
        private Keys mKey;
        private HotKeyHandler.Modifiers mModifier;
        public HotKeyPressedEventArgs(Keys Key, HotKeyHandler.Modifiers Modifier)
        {
            mKey = Key;
            mModifier = Modifier;
        }
        public Keys Key
        {
            get { return mKey; }
        }
        public HotKeyHandler.Modifiers Modifier
        {
            get { return mModifier; }
        }
    }
}
Dopo aver aggiunto questa classe al proprio progetto, per 
utilizzarla è sufficiente scrivere, ad esempio:
using HotKey;
//...
HotKeyHandler HotKey = new HotKeyHandler();
HotKey.Register(Keys.F12);
HotKey.Register(Keys.Q, HotKeyHandler.Modifiers.MOD_ALT);
HotKey.HotKeyPressed += new HotKeyHandler.HotKeyPressedEventHandler(HotKey_HotKeyPressed);
private void HotKey_HotKeyPressed(object sender, HotKeyPressedEventArgs e)
{
    if (e.Key == Keys.F12)
    {
        //...
    }
    else if (e.Key == Keys.Q && e.Modifier == HotKeyHandler.Modifiers.MOD_ALT)
    {
        //...
    }
}
Infine, per una corretta esecuzione, è bene richiamare il 
metodo Dispose dell'oggetto HotKeyHandler dopo aver terminato di lavorare con 
esso (tipicamente in fase di chiusura dell'applicazione).
powered by IMHO 1.3