言語フィルタ:
概要
ボタンにショートカットキーを割り当てる方法を紹介します。
対象コントロール
- System.Windows.Forms.Button
- System.Windows.Forms.ToolStripButton
解説
キーを入力してもボタンにフォーカスがなければ、ボタンは入力されたことを知ることが出来ません。コントロール上で入力されたキー情報はそのコントロールで処理されなかった場合、親コントロールへと伝えられていき、最終的にはフォームに伝えられます。フォームでキー情報を処理することで、ボタンにショートカットキーを割り当てることが出来ます。
伝えられるキー情報は Form.ProcessCmdKey メソッドで処理することができます。キー情報をショートカットキーとして処理した場合は True を返すようにします。これによりキー情報が処理されたことになり、それ以上親コントロールには伝えられなくなります。ショートカットキーの動作としてボタンをクリックするには Button または ToolStripButton の PerformClick メソッドを呼びます。
Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, ByVal keyData As System.Windows.Forms.Keys) As Boolean
' Ctrl + A をボタンのショートカットキーとして処理する
If keyData = Keys.Control + Keys.A Then
Me.Button1.PerformClick()
Return True
End If
Return MyBase.ProcessCmdKey(msg, keyData)
End Function
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
// Ctrl + A をボタンのショートカットキーとして処理する
if ((int)keyData == (int)Keys.Control + (int)Keys.A)
{
this.button1.PerformClick();
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
フォームでショートカットキーを処理しようとすると、コードに全てのボタンのショートカットキーを割り当てる処理を書かなければいけません。これではどのボタンにどんなショートカットキーを割り当てたのか、わかりづらくなってしまいます。そこで、ボタンにショートカットキーのプロパティがあるかのようにするために、拡張プロバイダを実装します。これによりデザイナ画面のボタンのプロパティウィンドウからショートカットキーを割り当てることが出来るようになります。
拡張プロバイダはコンポーネントに実装します。そのコンポーネントにショートカットキーの処理を行わせることで、簡単にショートカットキーの処理を行えるようになります。拡張プロバイダの詳しい実装方法はソースコードを参照してください。
ソースコード
Button コントロールと ToolStripButton コントロールにショートカットキーを割り当てるサンプルを紹介します。
ソースは Form にショートカットキーの拡張プロバイダを実装したコンポーネント ShortcutKeyHelper が貼り付けられています。Form.ProcessCmdKey メソッドでキー情報を ShortcutKeyHelper.PerformClickByKeys メソッドに渡し、ShortcutKeyHelper コンポーネントに処理を委譲しています。
ShortcutKeyHelper コンポーネントは IExtenderProvider インタフェースを実装しています。これで拡張プロバイダを実装出来るようになります。
ProvideProperty 属性の第一引数に拡張プロパティ名を指定します。Get[拡張プロパティ名]、 Set[拡張プロパティ名] メソッドがプロパティとして動作します。
ProvideProperty 属性の第二引数で拡張プロパティを提供するクラスの型を指定します。今回は Button コントロールと ToolStripButton コントロールの共通の基本クラスが MarshalByRefObject クラスのためそれを指定しています。
CanExtend メソッドに Form に貼り付けられているコントロールの中で ProvideProperty 属性に指定したクラスとその派生クラスが渡されてきます。拡張プロパティを Button コントロールと ToolStripButton コントロールに提供したいため、そのコントロールの時は True を返します。それ以外は False を返します。
Imports System
Imports System.Windows.Forms
Namespace Extentions
Public Class Form1
Inherits System.Windows.Forms.Form
Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, ByVal keyData As System.Windows.Forms.Keys) As Boolean
' ボタンに割り当てられたショートカットキーを処理する
If Me.ShortcutKeyHelper1.PerformClickByKeys(keyData) = True Then
Return True
End If
Return MyBase.ProcessCmdKey(msg, keyData)
End Function
End Class
End Namespace
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Windows.Forms
Namespace Extentions
<ProvideProperty("ShortcutKeys", GetType(MarshalByRefObject))> _
Public Class ShortcutKeyHelper
Inherits System.ComponentModel.Component
Implements IExtenderProvider
Private shortcutKeys As New Dictionary(Of MarshalByRefObject, Keys)
' 拡張プロバイダを提供する型の場合は True を返します。
Public Function CanExtend(ByVal extendee As Object) As Boolean Implements System.ComponentModel.IExtenderProvider.CanExtend
If TypeOf extendee Is Button OrElse TypeOf extendee Is ToolStripButton Then
Return True
End If
Return False
End Function
<DefaultValue(GetType(Keys), "None")> _
Public Function GetShortcutKeys(ByVal ctrl As MarshalByRefObject) As Keys
If Me.shortcutKeys.ContainsKey(ctrl) Then
Return Me.shortcutKeys(ctrl)
Else
Return Keys.None
End If
End Function
Public Sub SetShortcutKeys(ByVal ctrl As MarshalByRefObject, ByVal value As Keys)
If Me.shortcutKeys.ContainsKey(ctrl) Then
Me.shortcutKeys(ctrl) = value
Else
Me.shortcutKeys.Add(ctrl, value)
End If
End Sub
' ショートカットキーを割り当てたボタンのクリックイベントを発生させます。
Public Function PerformClickByKeys(ByVal keyData As Keys) As Boolean
If Me.shortcutKeys.ContainsValue(keyData) = False Then
Return False
End If
For Each t As KeyValuePair(Of MarshalByRefObject, Keys) In Me.shortcutKeys
If t.Value = keyData Then
If TypeOf t.Key Is Button Then
DirectCast(t.Key, Button).PerformClick()
Return True
End If
If TypeOf t.Key Is ToolStripButton Then
DirectCast(t.Key, ToolStripButton).PerformClick()
Return True
End If
End If
Next
Return False
End Function
End Class
End Namespace
using System;
using System.Windows.Forms;
namespace Extentions
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (this.shortcutKeyHelper1.PerformClickByKeys(keyData))
{
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
namespace Extentions
{
[ProvideProperty("ShortcutKeys", typeof(MarshalByRefObject))]
public partial class ShortcutKeyHelper : Component, IExtenderProvider
{
Dictionary<MarshalByRefObject, Keys> shortcutKeys = new Dictionary<MarshalByRefObject, Keys>();
public ShortcutKeyHelper()
{
InitializeComponent();
}
public ShortcutKeyHelper(IContainer container)
{
container.Add(this);
InitializeComponent();
}
#region IExtenderProvider メンバ
// 拡張プロバイダを提供する型の場合は True を返します。
bool IExtenderProvider.CanExtend(object extendee)
{
if ((extendee is Button) || (extendee is ToolStripButton))
{
return true;
}
return false;
}
#endregion
[DefaultValue(typeof(Keys), "None")]
public Keys GetShortcutKeys(MarshalByRefObject ctrl)
{
if (this.shortcutKeys.ContainsKey(ctrl))
{
return this.shortcutKeys[ctrl];
}
else
{
return Keys.None;
}
}
public void SetShortcutKeys(MarshalByRefObject ctrl, Keys value)
{
if (this.shortcutKeys.ContainsKey(ctrl))
{
this.shortcutKeys[ctrl] = value;
}
else
{
this.shortcutKeys.Add(ctrl, value);
}
}
// ショートカットキーを割り当てたボタンのクリックイベントを発生させます。
public bool PerformClickByKeys(Keys keyData)
{
if (this.shortcutKeys.ContainsValue(keyData) == false)
{
return false;
}
foreach (KeyValuePair<MarshalByRefObject, Keys> t in this.shortcutKeys)
{
if (t.Value == keyData)
{
if (t.Key is Button)
{
((Button)t.Key).PerformClick();
return true;
}
if (t.Key is ToolStripButton)
{
((ToolStripButton)t.Key).PerformClick();
return true;
}
}
}
return false;
}
}
}