How to: Stretch a ToolStripTextBox to Fill the Remaining Width of a ToolStrip (Windows Forms)

When you set the Stretch property of a ToolStrip control to true, the control fills its container from end to end, and resizes when its container resizes. In this configuration, you may find it useful to stretch an item in the control, such as a ToolStripTextBox, to fill the available space and to resize when the control resizes. This stretching is useful, for example, if you want to achieve appearance and behavior similar to the address bar in Microsoft® Internet Explorer.

Example

The following code example provides a class derived from ToolStripTextBox called ToolStripSpringTextBox. This class overrides the GetPreferredSize method to calculate the available width of the parent ToolStrip control after the combined width of all other items has been subtracted. This code example also provides a Form class and a Program class to demonstrate the new behavior.

using System;
using System.Drawing;
using System.Windows.Forms;

public class ToolStripSpringTextBox : ToolStripTextBox
{
    public override Size GetPreferredSize(Size constrainingSize)
    {        
        // Use the default size if the text box is on the overflow menu
        // or is on a vertical ToolStrip.
        if (IsOnOverflow || Owner.Orientation == Orientation.Vertical)
        {
            return DefaultSize;
        }

        // Declare a variable to store the total available width as 
        // it is calculated, starting with the display width of the 
        // owning ToolStrip.
        Int32 width = Owner.DisplayRectangle.Width;

        // Subtract the width of the overflow button if it is displayed. 
        if (Owner.OverflowButton.Visible)
        {
            width = width - Owner.OverflowButton.Width -
                Owner.OverflowButton.Margin.Horizontal;
        }

        // Declare a variable to maintain a count of ToolStripSpringTextBox 
        // items currently displayed in the owning ToolStrip. 
        Int32 springBoxCount = 0;

        foreach (ToolStripItem item in Owner.Items)
        {
            // Ignore items on the overflow menu.
            if (item.IsOnOverflow) continue;

            if (item is ToolStripSpringTextBox)
            {
                // For ToolStripSpringTextBox items, increment the count and 
                // subtract the margin width from the total available width.
                springBoxCount++;
                width -= item.Margin.Horizontal;
            }
            else
            {
                // For all other items, subtract the full width from the total
                // available width.
                width = width - item.Width - item.Margin.Horizontal;
            }
        }

        // If there are multiple ToolStripSpringTextBox items in the owning
        // ToolStrip, divide the total available width between them. 
        if (springBoxCount > 1) width /= springBoxCount;

        // If the available width is less than the default width, use the
        // default width, forcing one or more items onto the overflow menu.
        if (width < DefaultSize.Width) width = DefaultSize.Width;

        // Retrieve the preferred size from the base class, but change the
        // width to the calculated width. 
        Size size = base.GetPreferredSize(constrainingSize);
        size.Width = width;
        return size;
    }
}

public class Form1 : Form
{
    public Form1()
    {
        ToolStrip toolStrip1 = new ToolStrip();
        toolStrip1.Dock = DockStyle.Top;
        toolStrip1.Items.Add(new ToolStripLabel("Address"));
        toolStrip1.Items.Add(new ToolStripSpringTextBox());
        toolStrip1.Items.Add(new ToolStripButton("Go"));
        Controls.Add(toolStrip1);
        Text = "ToolStripSpringTextBox demo";
    }
}

static class Program
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }
}
Imports System
Imports System.Drawing
Imports System.Windows.Forms

Public Class ToolStripSpringTextBox
    Inherits ToolStripTextBox

    Public Overrides Function GetPreferredSize( _
        ByVal constrainingSize As Size) As Size

        ' Use the default size if the text box is on the overflow menu
        ' or is on a vertical ToolStrip.
        If IsOnOverflow Or Owner.Orientation = Orientation.Vertical Then
            Return DefaultSize
        End If

        ' Declare a variable to store the total available width as 
        ' it is calculated, starting with the display width of the 
        ' owning ToolStrip.
        Dim width As Int32 = Owner.DisplayRectangle.Width

        ' Subtract the width of the overflow button if it is displayed. 
        If Owner.OverflowButton.Visible Then
            width = width - Owner.OverflowButton.Width - _
                Owner.OverflowButton.Margin.Horizontal()
        End If

        ' Declare a variable to maintain a count of ToolStripSpringTextBox 
        ' items currently displayed in the owning ToolStrip. 
        Dim springBoxCount As Int32 = 0

        For Each item As ToolStripItem In Owner.Items

            ' Ignore items on the overflow menu.
            If item.IsOnOverflow Then Continue For

            If TypeOf item Is ToolStripSpringTextBox Then
                ' For ToolStripSpringTextBox items, increment the count and 
                ' subtract the margin width from the total available width.
                springBoxCount += 1
                width -= item.Margin.Horizontal
            Else
                ' For all other items, subtract the full width from the total
                ' available width.
                width = width - item.Width - item.Margin.Horizontal
            End If
        Next

        ' If there are multiple ToolStripSpringTextBox items in the owning
        ' ToolStrip, divide the total available width between them. 
        If springBoxCount > 1 Then width = CInt(width / springBoxCount)

        ' If the available width is less than the default width, use the
        ' default width, forcing one or more items onto the overflow menu.
        If width < DefaultSize.Width Then width = DefaultSize.Width

        ' Retrieve the preferred size from the base class, but change the
        ' width to the calculated width. 
        Dim preferredSize As Size = MyBase.GetPreferredSize(constrainingSize)
        preferredSize.Width = width
        Return preferredSize

    End Function
End Class

Public Class Form1
    Inherits Form

    Public Sub New()
        Dim toolStrip1 As New ToolStrip()
        With toolStrip1
            .Dock = DockStyle.Top
            .Items.Add(New ToolStripLabel("Address"))
            .Items.Add(New ToolStripSpringTextBox())
            .Items.Add(New ToolStripButton("Go"))
        End With
        Controls.Add(toolStrip1)
        Text = "ToolStripSpringTextBox demo"
    End Sub

End Class

Public Class Program

    <STAThread()> Public Shared Sub Main()
        Application.EnableVisualStyles()
        Application.SetCompatibleTextRenderingDefault(False)
        Application.Run(New Form1())
    End Sub

End Class

Compiling the Code

This example requires:

  • References to the System, System.Drawing, and System.Windows.Forms assemblies.

See Also

ToolStrip
System.Windows.Forms.ToolStrip.Stretch
ToolStripTextBox
System.Windows.Forms.ToolStripTextBox.GetPreferredSize
ToolStrip Control Architecture
How to: Use the Spring Property Interactively in a StatusStrip