Skip Navigation Linksホーム > ライブラリ > ボタン > ボタンにショートカットキーを割り当てる

ボタンにショートカットキーを割り当てる

言語フィルタ:

概要

ボタンにショートカットキーを割り当てる方法を紹介します。

対象コントロール

  • System.Windows.Forms.Button
  • System.Windows.Forms.ToolStripButton

解説

キーを入力してもボタンにフォーカスがなければ、ボタンは入力されたことを知ることが出来ません。コントロール上で入力されたキー情報はそのコントロールで処理されなかった場合、親コントロールへと伝えられていき、最終的にはフォームに伝えられます。フォームでキー情報を処理することで、ボタンにショートカットキーを割り当てることが出来ます。

伝えられるキー情報は Form.ProcessCmdKey メソッドで処理することができます。キー情報をショートカットキーとして処理した場合は True を返すようにします。これによりキー情報が処理されたことになり、それ以上親コントロールには伝えられなくなります。ショートカットキーの動作としてボタンをクリックするには Button または ToolStripButton の PerformClick メソッドを呼びます。

展開されたイメージ ショートカットキーを処理する - Visual Basic
コピーイメージ コードのコピー
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
展開されたイメージ ショートカットキーを処理する - C#
コピーイメージ コードのコピー
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 を返します。

展開されたイメージ Form のコード - Visual Basic
コピーイメージ コードのコピー
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
展開されたイメージ ShortcutKeyHelper のコード - Visual Basic
コピーイメージ コードのコピー
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
展開されたイメージ Form のコード - C#
コピーイメージ コードのコピー
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);
        }
    }
}
展開されたイメージ ShortcutKeyHelper のコード - C#
コピーイメージ コードのコピー
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;
        }
    }
}