API関数のRegisterHotKeyおよびUnregisterHotKeyを使用することで、ウィンドウハンドルに関連づけられたホットキーを設定・解除する事ができる。 ホットキーを指定する際は、キーコードと修飾キー(ALT, CTRL, SHIFT)及び、ホットキーのIDを指定する必要がある。 ホットキーのIDは、0x0000~0xBFFFの範囲でアプリケーションに一意な値を設定する必要がある。

登録したホットキーが実際に押されたときにはWM_HOTKEYメッセージが送られてくるので、これに対してフォームをアクティブにする記述をすれば、ホットキーが押された時点でフォームをアクティブにすることができる。 複数のホットキーから目的のものを識別するためには、lParamの値を比較する必要がある。

なお、RegisterHotKeyで指定するキーコード・修飾キーの値は、Keys列挙体の値を使うことができるが、修飾キーとして使えるWindowsロゴキーに該当するメンバがないので、個別に定数などを用意する必要がある。 さらに、システムや他のアプリケーションで既に使用されている場合は、そのホットキーを登録をすることはできない(RegisterHotKeyの呼び出しに失敗する)。

以下の例では、Ctrl+Spaceでフォームをアクティブにし、Win+Enter通知音(SystemSounds.Beep)を鳴らすようにホットキーの割り当てを行っている。

using System;
using System.ComponentModel;
using System.Media;
using System.Runtime.InteropServices;
using System.Windows.Forms;

/// <summary>ホットキーの登録・解除を行うためのクラス</summary>
class HotKey {
  [DllImport("user32", SetLastError = true)]
  private static extern int RegisterHotKey(IntPtr hWnd,
                                           int id,
                                           int fsModifier,
                                           int vk);

  [DllImport("user32", SetLastError = true)]
  private static extern int UnregisterHotKey(IntPtr hWnd,
                                             int id);

  public HotKey(IntPtr hWnd, int id, Keys key)
  {
    this.hWnd = hWnd;
    this.id = id;

    // Keys列挙体の値をWin32仮想キーコードと修飾キーに分離
    int keycode = (int)(key & Keys.KeyCode);
    int modifiers = (int)(key & Keys.Modifiers) >> 16;

    this.lParam = new IntPtr(modifiers | keycode << 16);

    if (RegisterHotKey(hWnd, id, modifiers, keycode) == 0)
      // ホットキーの登録に失敗
      throw new Win32Exception(Marshal.GetLastWin32Error());
  }

  public void Unregister()
  {
    if (hWnd == IntPtr.Zero)
      return;

    if (UnregisterHotKey(hWnd, id) == 0)
      // ホットキーの解除に失敗
      throw new Win32Exception(Marshal.GetLastWin32Error());

    hWnd = IntPtr.Zero;
  }

  public IntPtr LParam {
    get { return lParam; }
  }

  private IntPtr hWnd; // ホットキーの入力メッセージを受信するウィンドウのhWnd
  private readonly int id; // ホットキーのID(0x0000〜0xBFFF)
  private readonly IntPtr lParam; // WndProcメソッドで押下されたホットキーを識別するためのlParam値
}

public class Form1 : Form {
  static void Main()
  {
    Application.Run(new Form1());
  }

  private HotKey hotkeyActivate;
  private HotKey hotkeyNotify;

  protected override void OnLoad(EventArgs e)
  {
    const Keys modifierWinKey = (Keys)0x00080000; // Windowsロゴキー

    // Ctrl+SpaceをID 0のホットキーとして登録
    hotkeyActivate = new HotKey(this.Handle, 0, Keys.Control | Keys.Space);

    // Win+EnterをID 1のホットキーとして登録
    hotkeyNotify = new HotKey(this.Handle, 1, modifierWinKey | Keys.Enter);
  }

  protected override void OnClosing(CancelEventArgs e)
  {
    // 登録しているホットキーを解除
    hotkeyActivate.Unregister();
    hotkeyNotify.Unregister();
  }

  // ホットキーの入力メッセージを処理する
  protected override void WndProc(ref Message m)
  {
    const int WM_HOTKEY = 0x312;

    if (m.Msg == WM_HOTKEY && m.LParam == hotkeyActivate.LParam) {
      // フォームをアクティブにする
      Activate();
    }
    else if (m.Msg == WM_HOTKEY && m.LParam == hotkeyNotify.LParam) {
      // 通知音を鳴らす
      SystemSounds.Beep.Play();
    }
    else {
      base.WndProc(ref m);
    }
  }
}