DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

ToolStrip(ツールバー、メニュー、ステータスバー)に任意のコントロールを配置する

注意:ここで紹介している方法は、.NET Framework 2.0以降でのみ使用できます。

ToolStripコントロール(MenuStrip、ContextMenuStrip、StatusStripなどToolStripから派生したコントロールを含む)に配置できるアイテムには、色々なものが用意されています。例えばToolStripComboBoxクラスを使えばコンボボックスを、ToolStripTextBoxクラスを使えばテキストボックスを、ToolStripProgressBarクラスを使えばプログレスバーを配置することができます。しかし、それ以外のコントロールを配置するにはどのようにすればよいのでしょうか?

それを解決する方法がちゃんと用意されています。ToolStripControlHostクラスを使えば、任意のコントロールをToolStripにのせることができます。ここではToolStripControlHostを使用した例として、NumericUpDownコントロールをToolStripにのせる方法を説明します。

補足:ToolStripコントロールに配置できるアイテムは、ToolStripItemクラスから派生したもののみです。.NET Framework 2.0では、ToolStripItemクラスから派生したアイテムとして、以下のようなものが用意されています。
アイテム 説明
ToolStripButtonクラス ツールバーの普通のボタン。画像とテキストが表示できる。主に、ToolStripで使用される。
ToolStripDropDownButtonクラス 押すとドロップダウンリストが表示されるボタン。主に、ToolStrip、StatusStripで使用される。
ToolStripSplitButtonクラス ToolStripDropDownButtonと見た目が似ているが、こちらは普通のボタンとドロップダウンボタンが並んでいる。主に、ToolStrip、StatusStripで使用される。
ToolStripLabelクラス テキストや画像を表示できる。コメントやタイトル、あるいはハイパーリンクとして使用することもできる。主に、ToolStripで使用される。
ToolStripSeparatorクラス グループ分けするセパレータ。主に、ToolStrip、MenuStrip、ContextMenuStripで使用される。
ToolStripMenuItemクラス メニューで使われる項目。画像も表示可能。主に、MenuStrip、ContextMenuStripで使用される。
ToolStripStatusLabelクラス ステータスバーで使われるパネル。テキストや画像を表示できる。主に、StatusStripで使用される。
ToolStripComboBoxクラス コンボボックスを表示する。主に、ToolStrip、MenuStrip、ContextMenuStripで使用される。
ToolStripTextBoxクラス テキストボックスを表示する。主に、ToolStrip、MenuStrip、ContextMenuStripで使用される。
ToolStripProgressBarクラス ProgressBarを表示する。主に、ToolStrip、StatusStripで使用される。

ToolStripControlHostのコンストラクタにホストするコントロールを指定する

まずは、最もお手軽な方法を紹介します。ToolStripControlHostクラスのコンストラクタのパラメータにNumericUpDownオブジェクトを指定して、インスタンスを作成します。これをToolStripに追加すれば、OKです。

以下に示すコードは、すでにフォームに配置されているToolStripコントロール(ToolStrip1)にNumericUpDownコントロールをのせる例です。このコードは、ToolStrip1のあるフォームクラスに書かれてるものとします。

VB.NET
コードを隠すコードを選択
Private toolStripNumeric1 As ToolStripControlHost

'フォームのLoadイベントハンドラ
Private Sub Form1_Load(ByVal sender As Object, _
                       ByVal e As EventArgs) _
                       Handles MyBase.Load
    'ToolStripにのせるコントロール
    Dim ctrl As New NumericUpDown()
    'NumericUpDownをホストするToolStripControlHostを作成する
    Me.toolStripNumeric1 = New ToolStripControlHost(ctrl)

    'ToolStripに追加する
    ToolStrip1.Items.Add(toolStripNumeric1)
End Sub
C#
コードを隠すコードを選択
private ToolStripControlHost toolStripNumeric1;

//フォームのLoadイベントハンドラ
private void Form1_Load(object sender, System.EventArgs e)
{
    //ToolStripにのせるコントロール
    NumericUpDown ctrl = new NumericUpDown();
    //NumericUpDownをホストするToolStripControlHostを作成する
    this.toolStripNumeric1 = new ToolStripControlHost(ctrl);

    //ToolStripに追加する
    ToolStrip1.Items.Add(toolStripNumeric1);
}

NumericUpDownコントロールをToolStripにのせることはできましたが、NumericUpDownコントロールにアクセスするにはどのようにすればよいのでしょうか?例えば、現在の値(Valueプロパティ)を取得するには、どうしたらいいのでしょうか?

ToolStripControlHostがホストしているコントロールは、Controlプロパティで取得できるため、次のようなコードで、Valueプロパティの値を取得できます。

VB.NET
コードを隠すコードを選択
'NumericUpDownにキャストする
Dim ctrl As NumericUpDown = DirectCast(toolStripNumeric1.Control, NumericUpDown)
'NumericUpDownの値を取得する
Dim val As Decimal = ctrl.Value
C#
コードを隠すコードを選択
//NumericUpDownにキャストする
NumericUpDown ctrl = (NumericUpDown)toolStripNumeric1.Control;
//NumericUpDownの値を取得する
decimal val = ctrl.Value;

ToolStripControlHostの派生クラスを作成して、専用のクラスを作成する

次に、ToolStripControlHostの派生クラスを作成する方法を紹介します。このようにクラスを作成しておけば、ToolStripButtonなどと同様に、簡単にToolStripに追加できるようになります。

まず、次のようなクラスを作成します。あまりに簡単ですが、これだけで十分です。

VB.NET
コードを隠すコードを選択
Imports System.Windows.Forms

Public Class ToolStripNumericUpDown
    Inherits ToolStripControlHost

    Public Sub New()
        MyBase.New(New NumericUpDown())
    End Sub
End Class
C#
コードを隠すコードを選択
using System.Windows.Forms;

public class ToolStripNumericUpDown : ToolStripControlHost
{
    public ToolStripNumericUpDown() : base(new NumericUpDown())
    {
    }
}

これを実際にToolStripにのせる方法は、普通のToolStripItemをToolStripにのせる場合と同じです。コードで書くと、以下のようになります。

VB.NET
コードを隠すコードを選択
Private toolStripNumeric1 As ToolStripControlHost

'フォームのLoadイベントハンドラ
Private Sub Form1_Load(ByVal sender As Object, _
                       ByVal e As EventArgs) _
                       Handles MyBase.Load
    'ToolStripNumericUpDownオブジェクトを作成する
    toolStripNumeric1 = New ToolStripNumericUpDown()
    'ToolStripに追加する
    ToolStrip1.Items.Add(toolStripNumeric1)
End Sub
C#
コードを隠すコードを選択
private ToolStripControlHost toolStripNumeric1;

//フォームのLoadイベントハンドラ
private void Form1_Load(object sender, System.EventArgs e)
{
    //ToolStripNumericUpDownオブジェクトを作成する
    toolStripNumeric1 = new ToolStripNumericUpDown();
    //ToolStripに追加する
    ToolStrip1.Items.Add(toolStripNumeric1);
}

このようなコードを自分で書かずに、Visual Studioのフォームデザイナを使ってToolStripNumericUpDownをToolStripに配置することもできます。この方法は、「自作したToolStripItemをVisual Studioのデザイナで表示する」で説明します。

ToolStripにのせたNumericUpDownコントロールにアクセスする方法は前に説明した方法と同じで、ToolStripControlHost.Controlプロパティを使います。

更に改良する

これだけでも十分かもしれませんが、ToolStripNumericUpDownクラスをもう少し改良すると、さらに使いやすくなります。

まず、ホストしているNumericUpDownコントロールをプロパティで公開します。また、よく使うメソッドやプロパティもToolStripNumericUpDownクラスで公開します。ここでは、NumericUpDownの値を設定、取得するためのValueプロパティを作成します。

さらに、ToolStripNumericUpDownクラス内でNumericUpDownのイベントを処理する必要があれば、OnSubscribeControlEventsOnUnsubscribeControlEventsメソッドを使用すると、効率的です。ここでは、NumericUpDownの値が変化した時に発生するValueChangedイベントを追加することにします。

以上のように改良したToolStripNumericUpDownクラスは、次のようになります。

VB.NET
コードを隠すコードを選択
Imports System.Windows.Forms

Public Class ToolStripNumericUpDown
    Inherits ToolStripControlHost

    ''' <summary>
    ''' コンストラクタ
    ''' </summary>
    Public Sub New()
        MyBase.New(New NumericUpDown())
    End Sub

    ''' <summary>
    ''' ホストしているNumericUpDownコントロール
    ''' </summary>
    Public ReadOnly Property NumericUpDown() As NumericUpDown
        Get
            Return DirectCast(Control, NumericUpDown)
        End Get
    End Property

    ''' <summary>
    ''' 値の設定と取得
    ''' </summary>
    Public Property Value() As Decimal
        Get
            Return NumericUpDown.Value
        End Get
        Set(ByVal value As Decimal)
            NumericUpDown.Value = value
        End Set
    End Property

    'ホストしているNumericUpDownのイベントをサブスクライブする
    Protected Overrides Sub OnSubscribeControlEvents( _
            ByVal control As Control)
        MyBase.OnSubscribeControlEvents(control)
        Dim numControl As NumericUpDown = _
            DirectCast(control, NumericUpDown)
        AddHandler numControl.ValueChanged, _
            AddressOf NumericUpDown_OnValueChanged
    End Sub

    'ホストしているNumericUpDownのイベントをアンサブスクライブする
    Protected Overrides Sub OnUnsubscribeControlEvents( _
            ByVal control As Control)
        MyBase.OnUnsubscribeControlEvents(control)
        Dim numControl As NumericUpDown = _
            DirectCast(control, NumericUpDown)
        RemoveHandler numControl.ValueChanged, _
            AddressOf NumericUpDown_OnValueChanged
    End Sub

    ''' <summary> 
    ''' 値が変化した時に発生するイベント
    ''' </summary>
    Public Event ValueChanged As EventHandler

    'ValueChangedイベントを発生
    Private Sub NumericUpDown_OnValueChanged( _
            ByVal sender As Object, ByVal e As EventArgs)
        RaiseEvent ValueChanged(Me, e)
    End Sub
End Class
C#
コードを隠すコードを選択
using System.Windows.Forms;

public class ToolStripNumericUpDown : ToolStripControlHost
{
    /// <summary>
    /// コンストラクタ
    /// </summary>
    public ToolStripNumericUpDown() : base(new NumericUpDown())
    {
    }

    /// <summary>
    /// ホストしているNumericUpDownコントロール
    /// </summary>
    public NumericUpDown NumericUpDown
    {
        get
        {
            return (NumericUpDown)Control;
        }
    }

    /// <summary>
    /// 値の設定と取得
    /// </summary>
    public decimal Value
    {
        get
        {
            return NumericUpDown.Value;
        }
        set
        {
            NumericUpDown.Value = value;
        }
    }

    //ホストしているNumericUpDownのイベントをサブスクライブする
    protected override void OnSubscribeControlEvents(Control control)
    {
        base.OnSubscribeControlEvents(control);
        NumericUpDown numControl = (NumericUpDown)control;
        numControl.ValueChanged +=
            new EventHandler(NumericUpDown_OnValueChanged);
    }

    //ホストしているNumericUpDownのイベントをアンサブスクライブする
    protected override void OnUnsubscribeControlEvents(Control control)
    {
        base.OnUnsubscribeControlEvents(control);
        NumericUpDown numControl = (NumericUpDown)control;
        numControl.ValueChanged -=
            new EventHandler(NumericUpDown_OnValueChanged);
    }

    /// <summary>
    /// 値が変化した時に発生するイベント
    /// </summary>
    public event EventHandler ValueChanged;

    //ValueChangedイベントを発生
    private void NumericUpDown_OnValueChanged(object sender, EventArgs e)
    {
        if (ValueChanged != null)
        {
            ValueChanged(this, e);
        }
    }
}

改良したToolStripNumericUpDownクラスの使い方は、次のようになります。

VB.NET
コードを隠すコードを選択
Private toolStripNumeric1 As ToolStripNumericUpDown

Private Sub Form1_Load(ByVal sender As Object, _
                       ByVal e As EventArgs) _
                       Handles MyBase.Load
    'ToolStripNumericUpDownの作成
    toolStripNumeric1 = New ToolStripNumericUpDown()
    'toolStripNumeric1の値を変更
    toolStripNumeric1.Value = 5
    'ValueChangedイベントハンドラの追加
    AddHandler toolStripNumeric1.ValueChanged, _
        AddressOf toolStripNumeric1_ValueChanged
    'ToolStrip1に追加
    ToolStrip1.Items.Add(toolStripNumeric1)
End Sub

Sub toolStripNumeric1_ValueChanged( _
    ByVal sender As Object, ByVal e As EventArgs)
    Console.WriteLine("値が変わったよ")
End Sub
C#
コードを隠すコードを選択
private ToolStripNumericUpDown toolStripNumeric1;

//フォームのLoadイベントハンドラ
private void Form1_Load(object sender, System.EventArgs e)
{
    //ToolStripNumericUpDownの作成
    toolStripNumeric1 = new ToolStripNumericUpDown();
    //toolStripNumeric1の値を変更
    toolStripNumeric1.Value = 5;
    //ValueChangedイベントハンドラの追加
    toolStripNumeric1.ValueChanged +=
        new EventHandler(toolStripNumeric1_ValueChanged);
    //ToolStrip1に追加
    ToolStrip1.Items.Add(toolStripNumeric1);
}

void toolStripNumeric1_ValueChanged(object sender, EventArgs e)
{
    Console.WriteLine("値が変わったよ");
}
  • 履歴:
  • 2010/9/22 「ToolStripControlHostのコンストラクタにホストするコントロールを指定する」を追加。
  • 2013/7/16 誤字を修正。
  • 2014/9/15 ToolStripItemの派生クラスの説明を補足にした。タイトルを変更。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • イベントハンドラの意味が分からない、C#のコードをそのまま書いても動かないという方は、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。