高見知英のかいはつにっし(β)

高見知英のアプリケーション開発日誌 のほか、地域活動などの活動報告ブログ。

ホットキー登録クラス

 ついでに、↓の人たちに触発されて、.NETのホットキー登録クラスを作ってしまいました。
Windowsでホットキーを登録するのは割と簡単です。RegisterHotkey APIを使えば登録できるし、UnregisterHotkeyで登録解除できます。
WM_HOTKEYを捕まえなくてはいけないのですが、これも.NETならばWndProcをオーバーライドするだけなので、比較的簡単です。

protected override void WndProc(ref System.Windows.Forms.Message m)
{
  // WM_HOTKEY = 0x312 事前に宣言してあるものとする
  // 引数に押されたホットキーIDのみを持つ、OnHotkeyメソッドを呼び出す
  if(m.Msg == WM_HOTKEY) OnHotkey(m.WParam);
  base.WndProc(ref m);
}

 なれた人には常識ですが、最後のbase.WndProcを忘れないこと。これをしないとどんなウィンドウメッセージも処理されなくなり、結果コントロールが停止したようになってしまいます。

 まあ、とにかくこんなわけで、ホットキー自体は簡単。なのですが・・・。
むずかしいのはこれを"クラスとしてカプセル化する"コト。WM_HOTKEYはウィンドウハンドルに渡されるのですが、クラスにすると特定のウィンドウを見ることが出来なくなります。DelphiなどだとAllocateHWnd関数などがあるのでウィンドウハンドルを持つオブジェクトを簡単に作れますが、.NETの場合そんなものないので厄介です。
わたしは、とりあえずControlを継承してコントロールを作りました。

private class HotkeyObject : Control
{
  private const int WM_HOTKEY = 0x312;
  internal event HotkeyEventHandler Hotkey;
  protected override void WndProc(ref System.Windows.Forms.Message m)
  {
    if(m.Msg == WM_HOTKEY)
      if(Hotkey != null) Hotkey(this, new HotkeyEventArgs(m.WParam.ToInt32()));
        base.WndProc(ref m);
  }	    
}

こんな感じのクラスを生成して、これにWM_HOTKEYを送るようにします。DelphiのAllocateHWndなどより若干よけいなものが多い気がしますが、とりあえずこれで、無事ホットキー作成をクラス化することが出来ます。
Chie.Interop.dllに追加しておいたので、近く更新せねば。15〜しばらく休みのようなので、そのあたりを考えてみようかな。管理画面は間に合いそうにないので、今回は手編集か。まあ、よいでしょうね。
(ついでに上のクラスは継承してホットキーリストにも出来るので、HotkeyObjectはprotected以上のほうがよいかも。)