ホットキーに表示する各キーの名前は、System.Windows.Input.Key列挙体の値との対応を地道にコードで書きました。日本語キーボードはこんな感じで良いでしょう。英語キーボードには未対応。
Public Sub New()
InitializeComponent()
Hotkeys = New Dictionary(Of Key, String)
' A-Z, F1-F12
For Each k In New Key() {Key.A, Key.B, Key.C, Key.D, Key.E, Key.F, Key.G, Key.H, Key.I, Key.J, Key.K, Key.L, Key.M, Key.N, Key.O, Key.P, Key.Q, Key.R, Key.S, Key.T, Key.U, Key.V, Key.W, Key.X, Key.Y, Key.Z, _
Key.F1, Key.F2, Key.F3, Key.F4, Key.F5, Key.F6, Key.F7, Key.F8, Key.F9, Key.F10, Key.F11, Key.F12}
Hotkeys.Add(k, k.ToString)
Next
' D0-D9
For Each k In New Key() {Key.D0, Key.D1, Key.D2, Key.D3, Key.D4, Key.D5, Key.D6, Key.D7, Key.D8, Key.D9}
Hotkeys.Add(k, k.ToString.Chars(1))
Next
Hotkeys.Add(Key.Escape, "Esc")
Hotkeys.Add(Key.Back, "BackSpace")
Hotkeys.Add(Key.Tab, "Tab")
Hotkeys.Add(Key.Enter, "Enter")
Hotkeys.Add(Key.Space, "Space")
Hotkeys.Add(Key.Insert, "Insert")
Hotkeys.Add(Key.Delete, "Delete")
Hotkeys.Add(Key.Home, "Home")
Hotkeys.Add(Key.End, "End")
Hotkeys.Add(Key.PageUp, "PageUp")
Hotkeys.Add(Key.PageDown, "PageDown")
Hotkeys.Add(Key.Up, "Up")
Hotkeys.Add(Key.Left, "Left")
Hotkeys.Add(Key.Down, "Down")
Hotkeys.Add(Key.Right, "Right")
Hotkeys.Add(Key.NumLock, "NumLock")
Hotkeys.Add(Key.Divide, "Num /")
Hotkeys.Add(Key.Multiply, "Num *")
Hotkeys.Add(Key.Subtract, "Num -")
Hotkeys.Add(Key.Add, "Num +")
Hotkeys.Add(Key.Decimal, "Num .")
Hotkeys.Add(Key.NumPad0, "Num 0")
Hotkeys.Add(Key.NumPad1, "Num 1")
Hotkeys.Add(Key.NumPad2, "Num 2")
Hotkeys.Add(Key.NumPad3, "Num 3")
Hotkeys.Add(Key.NumPad4, "Num 4")
Hotkeys.Add(Key.NumPad5, "Num 5")
Hotkeys.Add(Key.NumPad6, "Num 6")
Hotkeys.Add(Key.NumPad7, "Num 7")
Hotkeys.Add(Key.NumPad8, "Num 8")
Hotkeys.Add(Key.NumPad9, "Num 9")
Select Case GetKeyboardType(0)
Case 7
' 日本語キーボード
Hotkeys.Add(Key.OemMinus, "-")
Hotkeys.Add(Key.OemQuotes, "^")
Hotkeys.Add(Key.OemPipe, "\(|)")
Hotkeys.Add(Key.OemTilde, "@")
Hotkeys.Add(Key.OemOpenBrackets, "[")
Hotkeys.Add(Key.OemPlus, "+")
Hotkeys.Add(Key.OemSemicolon, "*")
Hotkeys.Add(Key.OemCloseBrackets, "]")
Hotkeys.Add(Key.OemComma, ",")
Hotkeys.Add(Key.OemPeriod, ".")
Hotkeys.Add(Key.OemQuestion, "/")
Hotkeys.Add(Key.OemBackslash, "\(_)")
Hotkeys.Add(Key.ImeConvert, "変換")
Case Else
'
End Select
SetHotkey(Input.Key.None, Input.ModifierKeys.None)
End Sub
ホットキーコントロールのプロパティを作りました。ホットキーがセットされているか、修飾キー、キーの値が取れるようにしてます。あと読み取り専用です。設定する方法はメソッドで用意することにします。これは、修飾キーとキーを同時に設定する必要があるためです。
#Region "Properties"
Private Shared ReadOnly IsKeySetPropertyKey As DependencyPropertyKey = DependencyProperty.RegisterReadOnly("IsKeySet", GetType(Boolean), GetType(HotkeyControl), New FrameworkPropertyMetadata(Nothing))
Public Shared ReadOnly IsKeySetProperty As DependencyProperty = IsKeySetPropertyKey.DependencyProperty
Public Property IsKeySet() As Boolean
Get
Return GetValue(IsKeySetProperty)
End Get
Protected Set(ByVal value As Boolean)
SetValue(IsKeySetPropertyKey, value)
End Set
End Property
Private Shared ReadOnly ModifierPropertyKey As DependencyPropertyKey = DependencyProperty.RegisterReadOnly("Modifier", GetType(ModifierKeys), GetType(HotkeyControl), New FrameworkPropertyMetadata(Nothing))
Public Shared ReadOnly ModifierProperty As DependencyProperty = ModifierPropertyKey.DependencyProperty
Public Property Modifier() As ModifierKeys
Get
Return GetValue(ModifierProperty)
End Get
Protected Set(ByVal value As ModifierKeys)
SetValue(ModifierPropertyKey, value)
End Set
End Property
Private Shared ReadOnly KeyPropertyKey As DependencyPropertyKey = DependencyProperty.RegisterReadOnly("Key", GetType(Key), GetType(HotkeyControl), New FrameworkPropertyMetadata(Nothing))
Public Shared ReadOnly KeyProperty As DependencyProperty = KeyPropertyKey.DependencyProperty
Public Property Key() As Key
Get
Return GetValue(KeyProperty)
End Get
Protected Set(ByVal value As Key)
SetValue(KeyPropertyKey, value)
End Set
End Property
#End Region
TextBoxのPreviewKeyDownとPreviewKeyUpイベント処理。ここでは入力されたキーを表示します。PreviewKeyDownイベントでリアルタイムに押されているきーを表示。ただし、コンストラクタで設定したHotkeysコレクションにあるキーのみ。修飾キーを除いて複数のキーが押されていてもホットキーとしては登録できないので、1個のキーだけ表示します。さらに、CtrlだけやAltだけでもホットキーとして登録できないので、その場合PreviewKeyUpイベントでホットキーなしにします。
Private Sub TextBox_PreviewKeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Input.KeyEventArgs)
Dim text = New Text.StringBuilder
Me.Modifier = Keyboard.Modifiers
If CBool(Keyboard.Modifiers And ModifierKeys.Control) Then
text.Append("Ctrl + ")
End If
If CBool(Keyboard.Modifiers And ModifierKeys.Shift) Then
text.Append("Shift + ")
End If
If CBool(Keyboard.Modifiers And ModifierKeys.Alt) Then
text.Append("Alt + ")
End If
Me.IsKeySet = False
Me.Key = Input.Key.None
For Each k In Hotkeys
If Keyboard.IsKeyDown(k.Key) Then
text.Append(k.Value)
IsKeySet = True
Me.Key = k.Key
Exit For
End If
Next
If text.ToString <> "" Then
DirectCast(sender, TextBox).Text = text.ToString
End If
e.Handled = True
End Sub
Private Sub TextBox_PreviewKeyUp(ByVal sender As System.Object, ByVal e As System.Windows.Input.KeyEventArgs)
If Not IsKeySet Then
DirectCast(sender, TextBox).Text = "(Nothing)"
Me.Modifier = Input.ModifierKeys.None
Me.Key = Input.Key.None
End If
e.Handled = True
End Sub
Public Sub SetHotkey(ByVal key As Key, ByVal modifier As ModifierKeys)
Dim text = New Text.StringBuilder
If CBool(modifier And Input.ModifierKeys.Control) Then
text.Append("Ctrl + ")
End If
If CBool(modifier And Input.ModifierKeys.Shift) Then
text.Append("Shift + ")
End If
If CBool(modifier And Input.ModifierKeys.Alt) Then
text.Append("Alt + ")
End If
If Hotkeys.Keys.Contains(key) Then
IsKeySet = True
text.Append(Hotkeys(key))
TextBox.Text = text.ToString
Me.Modifier = modifier
Me.Key = key
Else
IsKeySet = False
TextBox.Text = "(Nothing)"
Me.Modifier = Input.ModifierKeys.None
Me.Key = Input.Key.None
End If
End Sub
Private Sub MenuItem_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
SetHotkey(Input.Key.None, Input.ModifierKeys.None)
End Sub
以上です。まだきちんと自分で使ってないのでバグってるかも。テスト用のウィンドウ。半角/全角キーとか押すとコードでは(Nothing)と設定しているはずなのに、テキストに反映されませんね。