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);
}
}
}
Imports System
Imports System.ComponentModel
Imports System.Media
Imports System.Runtime.InteropServices
Imports System.Windows.Forms
''' <summary>ホットキーの登録・解除を行うためのクラス</summary>
Class HotKey
<DllImport("user32", SetLastError := True)> _
Private Shared Function RegisterHotKey(ByVal hWnd As IntPtr, _
ByVal id As Integer, _
ByVal fsModifier As Integer, _
ByVal vk As Integer) As Integer
End Function
<DllImport("user32", SetLastError := True)> _
Private Shared Function UnregisterHotKey(ByVal hWnd As IntPtr, _
ByVal id As Integer) As Integer
End Function
Public Sub New(ByVal hWnd As IntPtr, ByVal id As Integer, ByVal key As Keys)
Me.hWnd = hWnd
Me.id = id
' Keys列挙体の値をWin32仮想キーコードと修飾キーに分離
Dim keycode As Integer = CInt(key And Keys.KeyCode)
Dim modifiers As Integer = CInt(key And Keys.Modifiers) >> 16
Me._lParam = New IntPtr(modifiers Or keycode << 16)
If RegisterHotKey(hWnd, id, modifiers, keycode) = 0 Then
' ホットキーの登録に失敗
Throw New Win32Exception(Marshal.GetLastWin32Error())
End If
End Sub
Public Sub Unregister()
If hWnd = IntPtr.Zero Then Return
If UnregisterHotKey(hWnd, id) = 0 Then
' ホットキーの解除に失敗
Throw New Win32Exception(Marshal.GetLastWin32Error())
End If
hWnd = IntPtr.Zero
End Sub
Public ReadOnly Property LParam As IntPtr
Get
Return _lParam
End Get
End Property
Private hWnd As IntPtr ' ホットキーの入力メッセージを受信するウィンドウのhWnd
Private ReadOnly id As Integer ' ホットキーのID(0x0000〜0xBFFF)
Private ReadOnly _lParam As IntPtr ' WndProcメソッドで押下されたホットキーを識別するためのlParam値
End Class
Public Class Form1
Inherits Form
Public Shared Sub Main()
Application.Run(New Form1())
End Sub
Private hotkeyActivate As HotKey
Private hotkeyNotify As HotKey
Protected Overrides Sub OnLoad(ByVal e As EventArgs)
Const modifierWinKey As Keys = CType(&h00080000, Keys) ' Windowsロゴキー
' Ctrl+SpaceをID 0のホットキーとして登録
hotkeyActivate = New HotKey(Me.Handle, 0, Keys.Control Or Keys.Space)
' Win+EnterをID 1のホットキーとして登録
hotkeyNotify = New HotKey(Me.Handle, 1, modifierWinKey Or Keys.Enter)
End Sub
Protected Overrides Sub OnClosing(ByVal e As CancelEventArgs)
' 登録しているホットキーを解除
hotkeyActivate.Unregister()
hotkeyNotify.Unregister()
End Sub
' ホットキーの入力メッセージを処理する
Protected Overrides Sub WndProc(ByRef m As Message)
Const WM_HOTKEY As Integer = &H312
If m.Msg = WM_HOTKEY AndAlso m.LParam = hotkeyActivate.LParam Then
' フォームをアクティブにする
Me.Activate()
Else If m.Msg = WM_HOTKEY AndAlso m.LParam = hotkeyNotify.LParam Then
' 通知音を鳴らす
SystemSounds.Beep.Play()
Else
MyBase.WndProc(m)
End If
End Sub
End Class