.NETプログラミング研究 第68号

.NET Tips

今回も前回に引き続き、ToolStripに関するTipsを紹介します。.NET Framework 2.0の新機能ですので、残念ながら1.0、1.1では使用できません。

ToolStripに任意のコントロールを配置する

注意

この記事の最新版は「ToolStripに任意のコントロールを配置する」で公開しています。

ToolStrip(MenuStrip、ContextMenuStrip、StatusStripなどToolStripから派生したコントロールを含む)に配置できるコントロールは、ToolStripItemクラスから派生したコントロールのみです。.NET Framework 2.0では、ToolStripItemクラスから派生したコントロールとして、以下のようなものが用意されています。

コントロール説明
ToolStripButtonツールバーの普通のボタン。画像とテキストが表示できる。主に、ToolStripで使用される。
ToolStripDropDownButton押すとドロップダウンリストが表示されるボタン。Exploreで言えば、「表示」ボタンのような感じ。主に、ToolStrip、StatusStripで使用される。
ToolStripSplitButtonToolStripDropDownButtonと似ているが、こちらはボタンとドロップダウンボタンが分かれている。Exploreで言えば、「戻る」や「進む」ボタンのような感じ。主に、ToolStrip、StatusStripで使用される。
ToolStripLabelテキストや画像を表示する。コメントやタイトルとして使う。主に、ToolStrip、StatusStripで使用される。
ToolStripSeparatorグループ分けするセパレータ。主に、ToolStrip、MenuStrip、ContextMenuStripで使用される。
ToolStripMenuItemメニューで使われる項目。画像も表示可能。主に、MenuStrip、ContextMenuStripで使用される。
ToolStripStatusLabelStatusStripで使われるパネル。テキストや画像を表示できる。主に、ToolStripで使用される。
ToolStripComboBoxコンボボックスを表示する。主に、ToolStrip、MenuStrip、ContextMenuStripで使用される。
ToolStripTextBoxテキストボックスを表示する。主に、ToolStrip、MenuStrip、ContextMenuStripで使用される。
ToolStripProgressBarProgressBarを表示する。主に、ToolStrip、StatusStripで使用される。

注意:「主に...で使用される。」というのは、そのToolStripItemをVisual Studioのデザイナを使って配置することができるToolStripの種類を示しています。デザイナを使わずに、コードでToolStripに追加する場合は、その限りではありません。

このように、以前のToolBarとは違い、ToolStripには多くのコントロールをのせることができます。

これだけでも十分かもしれませんが、さらに、任意のコントロールをToolStripにのせるための方法が用意されています。それが、ToolStripControlHostクラスです。ここではToolStripControlHostを使用した例として、NumericUpDownコントロールをToolStripにのせる方法を説明します。

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

  1
  2
  3
  4
  5
  6
  7
Public Class ToolStripNumericUpDown
    Inherits ToolStripControlHost
 
    Public Sub New()
        MyBase.New(New NumericUpDown())
    End Sub
End Class
  1
  2
  3
  4
  5
  6
  7
  8
using System.Windows.Forms;
 
public class ToolStripNumericUpDown : ToolStripControlHost
{
    public ToolStripNumericUpDown() : base(new NumericUpDown())
    {
    }
}

これを実際にToolStripにのせるには、次のようにします(フォームクラスに書かれてるものとします)。普通のToolStripItemをToolStripにのせる場合と同じです。

  1
  2
  3
  4
  5
  6
  7
  8
Private toolStripNumeric1 As ToolStripNumericUpDown
 
Protected Overrides Sub OnLoad(ByVal e As EventArgs)
    MyBase.OnLoad(e)
 
    toolStripNumeric1 = New ToolStripNumericUpDown()
    ToolStrip1.Items.Add(toolStripNumeric1)
End Sub
  1
  2
  3
  4
  5
  6
  7
  8
  9
private ToolStripNumericUpDown toolStripNumeric1;
 
protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
 
    toolStripNumeric1 = new ToolStripNumericUpDown();
    toolStrip1.Items.Add(toolStripNumeric1);
}

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

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

  1
Console.WriteLine(CType(toolStripNumeric1.Control, NumericUpDown).Value)
  1
Console.WriteLine(((NumericUpDown)toolStripNumeric1.Control).Value);

このように、たったこれだけのコードでも十分ですが、ToolStripNumericUpDownクラスをもう少し改良すると、さらに使いやすくなります。

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

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

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

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
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 CType(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 = _
            CType(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 = _
            CType(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
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
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クラスの使い方は、次のようになります(フォームクラスに書かれてるものとします)。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
Private toolStripNumeric1 As ToolStripNumericUpDown
 
Protected Overrides Sub OnLoad(ByVal e As EventArgs)
    MyBase.OnLoad(e)
 
    '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
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
private ToolStripNumericUpDown toolStripNumeric1;
 
protected override void OnLoad(EventArgs e)
{
    base.OnLoad(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("値が変わったよ");
}

参考:

自作したToolStripItemをVisual Studioのデザイナで表示する

注意

この記事の最新版は「自作したToolStripItemをVisual Studioのデザイナで表示する」で公開しています。

Visual Studioのデザイナでは、ToolStripの端に新しいToolStripItemを追加するためのボタンが表示され、これを使って簡単にToolStripItemを追加することができます。しかし、「ToolStripに任意のコントロールをのせる」で紹介したような自作のToolStripItemの場合はVisual Studioのデザイナに表示されないため、コードでToolStripに配置しなければなりません。ここでは、自作ToolStripItemをVisual Studioのデザイナで表示させる方法を紹介します。

自作のToolStripItemをデザイナで表示してToolStripに追加できるようにするには、ToolStripItemDesignerAvailability属性を使用します。例えば、次のようなToolStripNumericUpDownを定義すれば、フォームデザイナのToolStripとStatusStripでこのToolStripNumericUpDownを追加することができるようになります。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
<System.Windows.Forms.Design.ToolStripItemDesignerAvailability( _
    System.Windows.Forms.Design.ToolStripItemDesignerAvailability.ToolStrip _
    Or System.Windows.Forms.Design.ToolStripItemDesignerAvailability.StatusStrip)> _
Public Class ToolStripNumericUpDown
    Inherits ToolStripControlHost
 
    Public Sub New()
        MyBase.New(New NumericUpDown())
    End Sub
End Class
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
[System.Windows.Forms.Design.ToolStripItemDesignerAvailability(
   System.Windows.Forms.Design.ToolStripItemDesignerAvailability.ToolStrip |
   System.Windows.Forms.Design.ToolStripItemDesignerAvailability.StatusStrip)]
public class ToolStripNumericUpDown : ToolStripControlHost
{
    public ToolStripNumericUpDown()
        : base(new NumericUpDown())
    {
    }
}

さらに、デザイナでToolStripItemを追加する時のメニューで左側に表示される画像を変更するには、ToolboxBitmap属性を使います。(画像が指定されていないと、歯車の画像が表示されます。)

次の例では、「OpenFolder.bmp」という画像が「埋め込まれたリソース」としてアセンブリに埋め込まれている時に、これをToolStripNumericUpDownの画像としています。なお画像は、16X16の大きさである必要があります。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
<System.Windows.Forms.Design.ToolStripItemDesignerAvailability( _
    System.Windows.Forms.Design.ToolStripItemDesignerAvailability.ToolStrip _
    Or System.Windows.Forms.Design.ToolStripItemDesignerAvailability.StatusStrip), _
    ToolboxBitmap(GetType(ToolStripNumericUpDown), "OpenFolder.bmp")> _
Public Class ToolStripNumericUpDown
    Inherits ToolStripControlHost
 
    Public Sub New()
        MyBase.New(New NumericUpDown())
    End Sub
End Class
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
[System.Windows.Forms.Design.ToolStripItemDesignerAvailability(
   System.Windows.Forms.Design.ToolStripItemDesignerAvailability.ToolStrip |
   System.Windows.Forms.Design.ToolStripItemDesignerAvailability.StatusStrip)]
[ToolboxBitmap(typeof(ToolStripNumericUpDown), "OpenFolder.bmp")]
public class ToolStripNumericUpDown : ToolStripControlHost
{
    public ToolStripNumericUpDown()
        : base(new NumericUpDown())
    {
    }
}

これとは別に、ToolboxItem属性を使って画像を指定することもできます。この方法では、画像のほかに、表示名や説明を変更することもできます。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
<System.ComponentModel.ToolboxItem(GetType(NumericUpDownToolboxItem)), _
    System.Windows.Forms.Design.ToolStripItemDesignerAvailability( _
    System.Windows.Forms.Design.ToolStripItemDesignerAvailability.All)> _
Public Class ToolStripNumericUpDown
    Inherits ToolStripControlHost
 
    Public Sub New()
        MyBase.New(New NumericUpDown())
    End Sub
End Class
 
Public Class NumericUpDownToolboxItem
    Inherits System.Drawing.Design.ToolboxItem
 
    Public Sub New()
    End Sub
 
    Public Overrides Sub Initialize(ByVal type As Type)
        MyBase.Initialize(type)
 
        '説明
        Me.Description = "数字を入力できます。"
        '表示名
        Me.DisplayName = "数字入力"
        '画像
        Me.Bitmap = New Bitmap(GetType(NumericUpDownToolboxItem), _
            "OpenFolder.bmp")
    End Sub
End Class
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
[System.ComponentModel.ToolboxItem(typeof(NumericUpDownToolboxItem))]
[System.Windows.Forms.Design.ToolStripItemDesignerAvailability(
   System.Windows.Forms.Design.ToolStripItemDesignerAvailability.All)]
public class ToolStripNumericUpDown : ToolStripControlHost
{
    public ToolStripNumericUpDown()
        : base(new NumericUpDown())
    {
    }
}
 
public class NumericUpDownToolboxItem :
    System.Drawing.Design.ToolboxItem
{
    public NumericUpDownToolboxItem()
    {
    }
 
    public override void Initialize(Type type)
    {
        base.Initialize(type);
 
        //説明
        this.Description = "数字を入力できます。";
        //表示名
        this.DisplayName = "数字入力";
        //画像
        this.Bitmap = new Bitmap(typeof(NumericUpDownToolboxItem),
            "OpenFolder.bmp");
    }
}

ToolStripItemの位置をユーザーが変えられるようにする

注意

この記事の最新版は「ToolStripItemの位置をユーザーが変えられるようにする」で公開しています。

ToolStripのAllowDropプロパティをFalseとして、AllowItemReorderプロパティをTrueとすると、ユーザーがAltキーを押しながらToolStripItemをドラッグすることにより、その位置を変更することができます。

なお、AllowDropプロパティとAllowItemReorderプロパティの両方をTrueとすることはできません。

AllowItemReorderプロパティをTrueとしても移動できないToolStripItemも多く存在します。ToolStripComboBox、ToolStripProgressBar、ToolStripTextBoxなど、ToolStripControlHostを継承したToolStripItemは移動できないようです。

ToolStripItemの位置を保存、復元する方法は、前々号で説明したとおり、ToolStripManager.SaveSettings、LoadSettingsメソッドを使います。

このような方法とは別に、ダイアログを表示してToolStripItemの順番と表示・非表示を変更するサンプルが、MSDNの「ToolStrip のカスタマイズ サンプル」(CustomizeToolStripプロジェクト)にあります。

あるToolStripItemの右側に指定したToolStripItemが常にあるようにする

注意

この記事の最新版は「あるToolStripItemの右側に指定したToolStripItemが常にあるようにする」で公開しています。

例えば、ToolStripにToolStripComboBoxが配置されており、その説明のためにすぐ左側にToolStripLabelを配置した場合、常にToolStripLabelがToolStripComboBoxの左隣にないと意味不明になってしまいます。しかし、ToolStripのAllowItemReorderをTrueとしてユーザーがToolStripItemの位置を自由に変更できる時は、そうなってしまう可能性が十分あります。

これを防ぐために、あるToolStripItemの右側に指定したToolStripItemが常にあるようにする方法を考えてみました。いろいろな方法が考えられますが、ここではToolStripItemのLocationChangedイベントで処理することにします。

下に示す例では、ToolStripにToolStripLabel(toolStripLabel1)とToolStripComboBox(toolStripComboBox1)が配置されているとき、toolStripLabel1の右隣に常にtoolStripComboBox1があるようしています。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
'toolStripLabel1のLocationChangedイベントハンドラ
Private Sub toolStripLabel1_LocationChanged( _
    ByVal sender As Object, ByVal e As EventArgs) _
    Handles ToolStripLabel1.LocationChanged
 
    Dim item As ToolStripItem = CType(sender, ToolStripItem)
    If item.Equals(ToolStripLabel1) Then
        '常に隣にあるべきToolStripItem
        Dim nextItem As ToolStripItem = ToolStripComboBox1
        If Not (nextItem Is Nothing) And _
            Not (nextItem.Owner Is Nothing) Then
            If nextItem.Owner.Items.IndexOf(nextItem) <> _
                item.Owner.Items.IndexOf(item) + 1 Then
                '削除してから挿入する
                '削除しないと不具合が生じる可能性あり
                nextItem.Owner.Items.Remove(nextItem)
                Dim insertIndex As Integer = _
                    item.Owner.Items.IndexOf(item) + 1
                item.Owner.Items.Insert(insertIndex, nextItem)
            End If
        End If
    End If
End Sub
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
//toolStripLabel1のLocationChangedイベントハンドラ
private void toolStripLabel1_LocationChanged(
    object sender, EventArgs e)
{
    ToolStripItem item = (ToolStripItem)sender;
    if (item.Equals(toolStripLabel1))
    {
        //常に隣にあるべきToolStripItem
        ToolStripItem nextItem = toolStripComboBox1;
        if (nextItem != null && nextItem.Owner != null)
        {
            if (nextItem.Owner.Items.IndexOf(nextItem) !=
                item.Owner.Items.IndexOf(item) + 1)
            {
                //削除してから挿入する
                //削除しないと不具合が生じる可能性あり
                nextItem.Owner.Items.Remove(nextItem);
                int insertIndex = item.Owner.Items.IndexOf(item) + 1;
                item.Owner.Items.Insert(insertIndex, nextItem);
            }
        }
    }
}

この方法は、ユーザーが移動することのできないToolStripControlHostを継承したToolStripItemをユーザーが移動できるようにする方法としても使えるかもしれません。

ToolStripに関する取るに足らないTip

最後に、ここで述べるほどでは無いかもしれないつまらないTipをいくつか紹介します。

ToolStripItemを表示あるいは非表示にする / ToolStripItemが表示されているか調べる

注意

この記事の最新版は「ToolStripItemを表示あるいは非表示にする」で公開しています。

これは、Visibleプロパティを使えばよさそうですが、そう単純ではありません。ToolStripItemにはこれと同じような目的に使用する、Availableプロパティというものが存在するのです。

両者の違いについてMSDNでは、次のように書かれています(そのまま引用します)。

Available プロパティは、Visible プロパティとは異なります。Available が ToolStripItem を表示するかどうかを示すのに対し、Visible は ToolStripItem およびその親を表示するかどうかを示します。Available と Visible のいずれかを true または false に設定すると、他のプロパティも true または false に設定されます。

つまり、両者は値の設定に関しては全く同じであり、取得に関してのみ異なるということのようです。実際、VS2005のフォームデザイナのプロパティにはVisibleプロパティのみ表示され、Availableプロパティは表示されません。

取得される値がどのように異なるのか、具体的な例で説明しましょう。例えば、あるToolStripにToolStripItemが配置されており、ToolStripItemのVisibleとAvailableプロパティがTrueである場合、そのToolStripのVisibleをFalseに変更すると、ToolStripItemのVisibleもFalseになりますが、AvailableはTrueのままです。また、ToolStripItemをToolStripから削除した時も、VisibleはFalseになりますが、AvailableはTrueのままです。

MSDNによると設定に関しては両者に違いがないように思われますが、実際には違いが見られました。

私の確認した範囲では、別のToolStripItemの子となっているToolStripMenuItemの場合、AvailableプロパティをFalseにすることにより非表示にできますが、VisibleプロパティをFalseにしても非表示にできませんでした(正確には、VisibleプロパティをFalseにしようとしてもできません)。これは、オーバーフローボタンに入ったToolStripItemでもそうであるため、ToolStripItemがオーバーフローメニューに入っていない時はVisibleプロパティが使えるのに、オーバーフローメニューに入っていると使えなくなってしまうという奇妙なことになります。ToolStripMenuItemの表示、非表示をプログラムで行う時は、Availableプロパティを使った方が良さそうです。

メニューにToolTipを表示

注意

この記事の最新版は「メニューにToolTipを表示する」で公開しています。

MenuStripやContextMenuStripでは、今までのメニューと違って、ToolTipを簡単に表示することができます。MenuStripやContextMenuStripのShowItemToolTipsプロパティをTrueにして、ToolStripMenuItem.ToolTipTextプロパティにToolTipとして表示する文字列を指定するだけです。

また、ToolStripItem.AutoToolTipプロパティをTrueとすると、ToolTipTextが設定されていなくても、代わりにTextに設定された文字列がToolTipとして表示されます。

なおMSDNには、ToolStrip.ShowItemToolTipsをTrueとしないとToolTipが表示されないとありますが、MenuStripの場合はShowItemToolTipsをTrueとしなくても、ToolStripMenuItemにToolTipが表示されました。しかし今後のために、MenuStripでもShowItemToolTipsをTrueにしておいた方が良いでしょう。

右端にToolStripItemを配置

注意

この記事の最新版は「右端にToolStripItemを配置する」で公開しています。

ToolStripItem.AlignmentプロパティをRightとすることにより、ToolStripの右端にToolStripItemを配置することができます。これを使えば、よくある「ヘルプ」だけがメニューの右端にあるようなアプリケーションも簡単に作れます。

ただし、ToolStrip.LayoutStyleプロパティがTableまたはFlowの場合は、ToolStripItem.Alignmentプロパティが無視されてしまいます。

ToolStripButtonやToolStripMenuItemをクリックすると自動的にチェック状態が変化されるようにする

注意

この記事の最新版は「ToolStripButtonやToolStripMenuItemをクリックすると自動的にチェック状態が変化されるようにする」で公開しています。

ToolStripButtonとToolStripMenuItemにはCheckOnClickプロパティがあり、これをTrueにすることにより、クリックで自動的に状態が変わるようになります。

オーバーフローを有効にする

注意

この記事の最新版は「オーバーフローを有効にする」で公開しています。

ToolStripの幅をだんだん狭めていき、ToolStripItemが表示しきれなくなると、ToolStripの右側に下矢印のボタンが表示され、そのボタンを押すと、ToolStripに表示しきれなくなったToolStripItemがメニュー表示されます。この時、この下矢印のボタンを「オーバーフローボタン」(あるいは「オーバーフローシェブロン」)といい、ToolStripItemがオーバーフローボタンのメニューに入ることを「オーバーフロー(状態になった)」といいます。

オーバーフロー機能を有効にするには、ToolStripのCanOverflowプロパティがTrueで、さらにLayoutStyleプロパティがStackWithOverflowまたは、HorizontalStackWithOverflowやVerticalStackWithOverflowである必要があります。

また、ToolStripItemをオーバーフローボタンのメニューに移動させるかをToolStripItem.Overflowプロパティで指定できます。OverflowプロパティがAsNeededの時は必要な時のみ移動させ、Alwaysの時は常にメニューに表示し、Neverの時はメニューに移動せずに、ToolStripに収まらなくなったら、表示されなくなります。

補足:MSDNではToolStrip.CanOverflowプロパティの説明を、「ToolStrip 内の項目をオーバーフロー メニューに送信できるかどうかを示す値を取得または設定します。」としています。「オーバーフローメニューに送信」という意味が、オーバーフローメニューに移動するということであれば、この説明が正しいのか、疑問です。CanOverflowプロパティがFalseの時、OverflowプロパティがAlwaysのToolStripItemはToolStripに全く表示されません(ToolStrip.LayoutStyleプロパティがTableまたはFlowの時は、表示されます)。これは多分、OverflowがAlwaysのToolStripItemがオーバーフローメニューに移動したが、オーバーフローボタンが表示されなくなったため見えなくなったものと考えられます。つまり、CanOverflowプロパティはオーバーフローボタンを表示するかどうかを指定するものと解釈した方が良さそうです。(説明が正しく、動作が間違っている可能性もありますが。)

ToolStripItemがオーバーフロー状態になったことを知る

注意

この記事の最新版は「ToolStripItemがオーバーフロー状態になったことを知る」で公開しています。

ToolStripItemがオーバーフロー状態になったことを知るためのイベントは存在しません。しかし、MSDNの「方法 : Windows フォームの ToolStrip オーバーフローを管理する」によると、ToolStripのLayoutCompletedイベントが発生した時に、ToolStripItem.Placementプロパティの値を調べて、ToolStripItemがオーバーフロー状態か調べることができるということです。

実際のコードは、例えば、次のようになりそうです。ここでは、toolStripButton1のオーバーフロー状態を監視しています。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
Private toolStripButton1Placement As ToolStripItemPlacement = _
    ToolStripItemPlacement.None
 
'toolStrip1のLayoutCompletedイベントハンドラ
Private Sub toolStrip1_LayoutCompleted( _
    ByVal sender As Object, ByVal e As EventArgs) _
    Handles ToolStrip1.LayoutCompleted
 
    If ToolStripButton1.Placement <> toolStripButton1Placement Then
        If ToolStripButton1.Placement = ToolStripItemPlacement.Overflow Then
            Console.WriteLine( _
                "toolStripButton1がオーバーフロー状態になりました")
        Else
            If ToolStripButton1.Placement = ToolStripItemPlacement.Main Then
                Console.WriteLine( _
                    "toolStripButton1がオーバーフロー状態ではなくなりました")
            End If
        End If
        toolStripButton1Placement = ToolStripButton1.Placement
        Console.WriteLine(DateTime.Now)
    End If
End Sub
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
private ToolStripItemPlacement toolStripButton1Placement =
    ToolStripItemPlacement.None;
 
//toolStrip1のLayoutCompletedイベントハンドラ
private void toolStrip1_LayoutCompleted(object sender, EventArgs e)
{
    if (toolStripButton1.Placement != toolStripButton1Placement)
    {
        if (toolStripButton1.Placement == ToolStripItemPlacement.Overflow)
        {
            Console.WriteLine(
                "toolStripButton1がオーバーフロー状態になりました");
        }
        else if (toolStripButton1.Placement == ToolStripItemPlacement.Main)
        {
            Console.WriteLine(
                "toolStripButton1がオーバーフロー状態ではなくなりました");
        }
        toolStripButton1Placement = toolStripButton1.Placement;
        Console.WriteLine(DateTime.Now);
    }
}

実際に試してみると分かりますが、toolStripButton1がすでにオーバーフロー状態となっていても、toolStrip1の幅を変えた時に、「オーバーフロー状態になりました」と「オーバーフロー状態ではなくなりました」が連続して表示されることがあります。

補足:ToolStripのオーバーフローボタンの実体は、ToolStripOverflowButtonというToolStripItemであり、ToolStrip.OverflowButtonプロパティで取得することができます。よって、DropDownItemsプロパティで現在オーバーフロー状態となっているすべてのアイテムを取得できそうですが、実際にはできません。しかし、HasDropDownItemsプロパティは使えるようです。

ToolStripの幅に応じてToolStripItemのDisplayStyleを変更する

注意

この記事の最新版は「ToolStripの幅に応じてToolStripItemのDisplayStyleを変更する」で公開しています。

MSDNの「ToolStrip サンプル」には、「DynamicOverflowForm」というサンプルが用意されています。これは、ToolStripの幅が狭くなってToolStripItemが表示しきれなくなった時に、ToolStripItemのDisplayStyleプロパティを変更してその幅を縮めることによって、ToolStripItemがオーバーフローとなることをできるだけ防ぐというものです。はじめはすべてのToolStripItemのDisplayStyleがImageAndTextとなっていますが、ToolStripの幅を狭めていくと、ToolStripItemのDisplayStyleがText、Imageと変化していきます。

なかなか面白いサンプルですので、一度お試しください。

コメント



ページ情報
  • カテゴリ : .NET
  • 作成日 : 2006-04-05 (水) 06:00:00
  • 作成者 : DOBON!
  • 最終編集日 : 2010-03-23 (火) 02:39:38
  • 最終編集者 : DOBON!
[ トップ ]   [ 編集 | 凍結 | 差分 | バックアップ | 添付 | 複製 | 名前変更 | リロード ]   [ 新規 | 子ページ作成 | 一覧 | 単語検索 | 最終更新 | ヘルプ ]