Click here to Skip to main content
Click here to Skip to main content

A Status Bar Text Provider for Menu Items and Form Controls

, 7 Jul 2006
Rate this:
Please Sign up or sign in to vote.
A status bar text provider for menu items and form controls in Windows Forms applications similar to the feature found in MFC and Microsoft Access applications.

Introduction

In an MFC application, the status bar text for menu items is a built-in feature. In the menu resource editor, you specify the text and, at runtime, as you move from menu item to menu item, a description will appear in the status bar for each one. By default, this functionality is missing from .NET Windows Forms applications. However, by using a component that implements the IExtenderProvider interface, it is quite easy to add this feature, complete with design-time support, and only requires you to manually write a line or two of actual code. As a bonus, you can also use it to add status bar text for any control on a form, similar to the StatusBarText property in controls found in Microsoft Access.

Status Bar Text Provider Features

The StatusBarTextProvider is an IExtenderProvider component that allows you to add status bar text for menu items and form controls. When built for use with .NET 2.0, it also supports status text on menu strip, tool strip, and status strip items. It provides the following features:

  • When the component is dropped on the form, MenuItem components, all Control type items, and ToolStripItem components are extended with an extra StatusBar category in their property window containing the StatusBarText and ShowAsBlank properties. The following items are not extended: Form, Label, PictureBox, ProgressBar, ScrollBar, Splitter, StatusBar, ToolBar, ToolStrip, and controls derived from them. The Form contains controls, and the other controls cannot receive the focus needed to display the text, so there is no point in giving them status bar text. The exception to the above rule is LinkLabel, which can receive the focus and thus can be extended.
  • The StatusBarText property is used to set the text to display in the status bar when the item has the focus.
  • The ShowAsBlank property can be used to have the item show a blank status bar when it has the focus. This property is necessary as the Visual Studio .NET designer converts strings of spaces to an empty string, and thus it does not serialize the blank string to code. Setting this property to true obtains the desired result of blank status bar text for the item.
  • The provider can use a common status bar on the application's main form (i.e., an MDI container), or it can use a status bar local to the form that contains it (i.e., a dialog box).
  • The provider can be configured to display the status bar text in any panel defined in the status bar. If the status bar does not have panels defined, it will use the status bar's Text property instead.
  • When built for use with .NET 2.0, you can specify any ToolStripStatusLabel component as the place to display the text. Note that since status labels can appear in toolbars as well, you are not limited to displaying text in the application status bar for items.
  • The provider works with modal and non-modal forms in single document interface (SDI) and multiple document interface (MDI) applications.
  • Status bar text is correctly restored to its prior value when leaving a control, closing a form, switching between forms, and when entering or exiting a menu.
  • Status bar text can be set on container controls such as GroupBox and Panel, and on classes derived from UserControl, to provide status bar text for controls within them that do not have status bar text specified for themselves.
  • UserControl objects can supply their own status bar text provider to define status bar text for the controls that they contain.
  • When built for use with .NET 2.0, two extra static properties are provided (StatusLabel and ProgressBar) that can be used to gain access to a status label and progress bar on the main status strip for the application, to provide progress feedback for long running processes from anywhere within the application. In order to make using them easier, three overloaded methods are also provided:
    • InitializeProgressBar - This is used to initialize the status label and progress bar for use (six overloads).
    • UpdateProgress - This is used to update the status label and progress bar as you move through an operation (four overloads).
    • ResetProgressBar - This is used to reset the status label and progress bar when done (two overloads).

The supplied demo contains the assembly, a help file, and a demo application. Versions are supplied for .NET 1.1 and .NET 2.0. See the help file for details on installing the assembly in the Visual Studio .NET tool box. You can also extract the StatusBarTextProvider.cs source file for use in your own projects or control libraries.

Using the Assembly in your Projects

The classes can be found in the assembly EWSoftware.StatusBarText.dll. In order to use the classes, add a reference to it in your project. The help file contains details on how to do this, if you need it. In the code modules that use classes from the EWSoftware.StatusBarText namespace, you will have to add a using statement (Imports in VB.NET) for the EWSoftware.StatusBarText namespace.

Naturally, you must add a status bar control (.NET 1.1), or a status strip control containing at least one status label (.NET 2.0), to your form.

.NET 1.1 Setup

To define the common application status bar used by all instances of StatusBarTextProvider, and optionally the display panel to use, add code similar to the following to your main form's constructor, to set the static ApplicationStatusBar and ApplicationDisplayPanel properties:

// Define the default status bar to use in
// the main form's constructor
public MainForm()
{
    InitializeComponent();

    // Tell the StatusBarTextProvider component the status bar to use
    StatusBarTextProvider.ApplicationStatusBar = sbStatusBar;

    // You can also use any panel you like. The default is zero
    // (the left-most panel). For the demo, we'll use the one
    // in the middle.
    StatusBarTextProvider.ApplicationDisplayPanel = 1;
}

If your status bar control does not contain panels, you can omit setting the ApplicationDisplayPanel property, and the provider will use the status bar's Text property to display the text instead.

.NET 2.0 Setup

Although not formally deprecated, the standard MainMenu, ToolBar, and StatusBar controls have been replaced by the MenuStrip, ToolStrip, and StatusStrip controls. In fact, the old controls do not appear in the toolbox, by default. When you get time, it would be a good idea to update any existing applications to use the newer controls, as they provide some new features such as the ability to put text boxes, combo boxes, or progress bar controls directly in the tool strips and status strips and to have images on the menu items.

When using a status strip, you specify the status label tool strip item used by all instances of StatusBarTextProvider rather than a status bar component. Add code similar to the following to your main form's constructor, to set the static ApplicationStatusBar property. If your status strip also contains a label and/or progress bar tool strip item, you can set the static StatusLabel and ProgressBar properties as well provide all forms in your application convenient access to them and make use of the status methods for them on the provider, as noted earlier.

// Define the default status strip label to use in
// the main form's constructor.
public MainForm()
{
    InitializeComponent();

    // Tell the StatusBarTextProvider component the component
    // to use to display the text. When using a tool strip
    // component, the ApplicationDisplayPanel property is ignored.
    StatusBarTextProvider.ApplicationStatusBar = tslStatusText;

    // Define the status label and progress bar too. This allows
    // easy access to those items from anywhere within the
    // application.
    StatusBarTextProvider.StatusLabel = tslProgressNote;
    StatusBarTextProvider.ProgressBar = tspbProgressBar;
}

Since a tool strip item is used in this situation, the ApplicationDisplayPanel property is always ignored.

The Instance Status Bar

Optionally, you can use the InstanceStatusBar and InstanceDisplayPanel properties in code to override the application-level status bar and display panel settings on a form-by-form basis. The example code below is from the demo, and is used to switch between using the child form's status bar and the main form's status bar. sbMessage is the status bar text provider for the child form, and ucDemo.StatusBarTextProvider is used to access the status bar text provider for a user control that appears on the child form.

private void chkUseDialog_CheckedChanged(object sender, System.EventArgs e)
{
    if(chkUseDialog.Checked)
    {
        // Use the dialog box's status bar when checked
        sbMessage.InstanceStatusBar = sbDialog;
        ucDemo.StatusBarTextProvider.InstanceStatusBar = sbDialog;

        // Make the instance default text the same for any nested
        // status bar text providers. If not, they pick up the
        // status bar text of the current control as the default.
        ucDemo.StatusBarTextProvider.InstanceDefaultText =
            sbMessage.InstanceDefaultText;
    }
    else
    {
        // Go back to using the main form's status bar
        sbMessage.InstanceStatusBar = null;
        ucDemo.StatusBarTextProvider.InstanceStatusBar = null;
    }
}

Design-time Support

To use the StatusBarTextProvider, simply drag it from the toolbox and drop it on your form. Once done, all MenuItem components, Control type objects, and ToolStripItem components on the form will have an extra StatusBar category in their property window. Using it, you can set the StatusBarText and ShowAsBlank properties.

Normally, you will just enter a message to display in the StatusBarText property. As noted above, the ShowAsBlank property exists so that in the rare event when you want a blank status bar for an item, you can set this property to true. The designer converts a string containing nothing but spaces to an empty string. Since this is the default value, it does not get serialized to code, thus the extra property is needed.

Status Bar Text on TabControl and TabPage Controls

TabControl and TabPage controls do not always reliably show their status bar text due to the way they handle the focus. Steps have been taken to allow status bar text on these controls, but there are a couple of known problems with no workarounds:

  • First and foremost is the requirement that you set the ShowAsBlank property to true, or define some StatusBarText for the TabControl itself so that status bar text can be displayed for the individual tab pages. This refers to the text shown if a control on a page has no status bar text, or when the tab itself has the focus. As with other container controls, if you do not define status bar text for the tab pages, the status bar text for the tab control will be shown instead.
  • The tab control will not show the status bar text if you use Shift+Tab to go from the first control on a tab back to the tab itself or, occasionally, when it is the first control to have the focus when the form is opened. Moving from one tab to another or moving the focus to a control outside the tab control and then back to the tab control will get it to start showing the status bar text for the tabs again.

One final note regarding the designer: When setting the status bar text for the tab pages, be sure to actually click on a part of the tab page to ensure that it is selected. If you just click the tab in the tab control's header to select it, the tab control will have the focus in the designer, and you may inadvertently modify the tab control's status bar text rather than the text for the tab page.

Status Text on Tool Strip Items

Under .NET 2.0, status bar text can be specified for menu strip, tool strip, and status strip items. However, there are a few limitations with no workarounds.

  • For menu strip items, text is only displayed when the mouse moves in and out of the menu items. If navigating the menus with the keyboard, the status text is not displayed. Unfortunately, the menu strip items do not fire selection events like the menu items from .NET 1.1, so it is not possible to display text for them in this situation.
  • For tool strip and status strip items, status text will be shown when you move the mouse over them. In addition, if you tab into a combo box or a text box, the status text will update. However, when tabbing onto a button control, no status text will be displayed. As with the menu strip items, there is no selection event to hook to enable it.
  • With the prior version of this control under .NET 1.1, it was always possible to restore the prior text when moving from a form, to the menu, and back to the form. However, under .NET 2.0 with the above limitations, I had to make a compromise and rework how the original status bar text was restored. This affects the component under both .NET 1.1 and .NET 2.0. As such, there are some cases where when moving from a menu back to the form, the status bar text for the current control will not be displayed. Instead, the default text will appear in the status bar. Tabbing out of the control and back in will display the correct text again.

How it Works

To create an extender provider, you need to derive a class from Component and implement the IExtenderProvider interface. The interface contains a single method (CanExtend) that returns true or false based on whether or not it can provide its properties to the object it receives as a parameter. In this case, we check the type of the passed object to see if it is the one that we can extend.

Throughout the following code, the DOTNET_20 definition is used to conditionally compile code related to the modifications needed to support the .NET 2.0 components. It is defined at the top of the file. Comment it out to build the code under .NET 1.1.

public class StatusBarTextProvider : Component, IExtenderProvider
{
    /// <span class="code-SummaryComment"><summary></span>
    /// Default constructor
    /// <span class="code-SummaryComment"></summary></span>
    public StatusBarTextProvider()
    {
        htOptions = new Hashtable(25);
    }

    /// <span class="code-SummaryComment"><summary></span>
    /// Constructor. This one takes a reference to a container.
    /// <span class="code-SummaryComment"></summary></span>
    /// <span class="code-SummaryComment"><param name="container">The container for the</span>
    /// component<span class="code-SummaryComment"></param></span>
    public StatusBarTextProvider(IContainer container) : this()
    {
        if(container != null)
            container.Add(this);
    }

    /// <span class="code-SummaryComment"><summary></span>
    /// This is implemented to determine if the component can be
    /// extended with the extra properties.
    /// <span class="code-SummaryComment"></summary></span>
    /// <span class="code-SummaryComment"><param name="extendee">The object to check</param></span>
    public bool CanExtend(object extendee)
    {
        // MenuItem is a Component. LinkLabel derives from Label but
        // it can gain the focus and thus can be extended. For .NET 2.0,
        // we also support the ToolStripItem component.
#if !DOTNET_20
        if(extendee is MenuItem || extendee is LinkLabel)
#else
        if(extendee is MenuItem || extendee is LinkLabel ||
          extendee is ToolStripItem)
#endif
            return true;

        // Non-Control types, Form, and these specific controls can't be
        // extended as it doesn't make sense for them as they don't gain
        // the focus needed to display the text.
        if(!(extendee is Control) || extendee is Form ||
          extendee is Label || extendee is PictureBox ||
          extendee is ProgressBar || extendee is ScrollBar ||
          extendee is Splitter || extendee is StatusBar ||
#if !DOTNET_20
          extendee is ToolBar)
#else
          extendee is ToolBar || extendee is ToolStrip)
#endif
            return false;

        // All other Control types can be extended
        return true;
    }
}

In addition, you need to specify the ProvideProperty attributes on the class for each extended property that you will provide. The attribute takes the name of the property and the type to which it applies. In the case of the StatusBarTextProvider, I chose to specify Component as the type so that it can be applied in a generic fashion to menu items, controls, and tool strip items alike.

[ProvideProperty("StatusBarText", typeof(Component)),
 ProvideProperty("ShowAsBlank", typeof(Component))]
public class StatusBarTextProvider : Component, IExtenderProvider
{
    ... class code ...
}

The next step is to actually implement the code for the provided properties. Although they act like properties in the designer, you actually create two methods (a GetXXX and a SetXXX method where XXX is the name of the property). The Get method receives a reference to the object that is being extended. The Set method receives a reference to the object that is being extended and a value for the extended property. The type for the object should match the type specified in the attribute. The type for the value parameter received by the Set method can be any type that you need. Internally, you are free to track and store the values as you see fit. The easiest approach is to create a hash table, and use the object as the key and the value parameter as the value for the hash table entry. If you are providing multiple properties as in the case of the StatusBarTextProvider, it is worthwhile to create a separate class for the properties and use that as the item to store in the hash table.

/// <span class="code-SummaryComment"><summary></span>
/// This class contains the options for the items that need status
/// bar text.
/// <span class="code-SummaryComment"></summary></span>
private sealed class PropertyOptions
{
    //============================================================
    // Private data member

    private string message;
    private bool showAsBlank;

    //============================================================
    // Properties

    /// <span class="code-SummaryComment"><summary></span>
    /// Set or get the message text
    /// <span class="code-SummaryComment"></summary></span>
    public string Message
    {
        get { return message; }
        set { message = value; }
    }

    /// <span class="code-SummaryComment"><summary></span>
    /// The "show as blank" flag
    /// <span class="code-SummaryComment"></summary></span>
    public bool ShowAsBlank
    {
        get { return showAsBlank; }
        set { showAsBlank = value; }
    }

    //============================================================
    // Methods, etc.

    /// <span class="code-SummaryComment"><summary></span>
    /// Constructor
    /// <span class="code-SummaryComment"></summary></span>
    /// <span class="code-SummaryComment"><param name="msg">The message text to display</param></span>
    /// <span class="code-SummaryComment"><overloads>There are two overloads for the</span>
    /// constructor<span class="code-SummaryComment"></overloads></span>
    public PropertyOptions(string msg)
    {
        message = msg;
    }

    /// <span class="code-SummaryComment"><summary></span>
    /// Constructor
    /// <span class="code-SummaryComment"></summary></span>
    /// <span class="code-SummaryComment"><param name="showBlank">The "show as blank"</span>
    /// flag<span class="code-SummaryComment"></param></span>
    public PropertyOptions(bool showBlank)
    {
        showAsBlank = showBlank;
    }
}

Here is an example of a Get method for the StatusBarText property. After some checks to make sure the passed component is valid and is supported, it simply checks to see if the hash table contains the component. If it does, it casts the value from the hash table to our property options class from above, and returns the message text from it. If the hash table does not contain the component yet, it returns null. Also note that you can provide design-time attributes on the Get method such as Category, DefaultValue, etc., to provide better designer support for the extender provider.

/// <span class="code-SummaryComment"><summary></span>
/// This is used to retrieve the status bar text for a component.
/// <span class="code-SummaryComment"></summary></span>
/// <span class="code-SummaryComment"><param name="comp">The component for which to get the</span>
/// status bar text<span class="code-SummaryComment"></param></span>
/// <span class="code-SummaryComment"><returns>The message string if found or null if not</span>
/// found<span class="code-SummaryComment"></returns></span>
[Category("StatusBar"), Localizable(true), DefaultValue(null),
  Description("The status bar text for the item")]
public string GetStatusBarText(Component comp)
{
    if(comp == null)
        throw new ArgumentException("Component cannot be null");

#if !DOTNET_20
    if(!(comp is MenuItem) && !(comp is Control))
#else
    if(!(comp is MenuItem) && !(comp is Control) &&
      !(comp is ToolStripItem))
#endif
        throw new ArgumentException(
            "Component must be a MenuItem, ToolStripItem, " +
                "or a Control");

    if(htOptions.Contains(comp))
        return ((PropertyOptions)htOptions[comp]).Message;

    return null;
}

The Set method works in a similar fashion. If the hash table does not contain the component, you create an instance of the property options class, store the value in it, and add it to the hash table. If the component is already in the hash table, you simply retrieve the existing settings and update them with the new value.

In the case of StatusBarTextProvider, things get a little more complicated. In addition to storing the property value, we also need to hook up several events so that we can adjust the status bar text as the various controls and menu items gain and lose focus. The first part is fairly straightforward. We check to make sure the object is valid, and create some helper variables that will let us determine the type of the object so that we can hook up or disconnect the appropriate events.

/// <span class="code-SummaryComment"><summary></span>
/// This stores the status bar text for the specified component.
/// <span class="code-SummaryComment"></summary></span>
/// <span class="code-SummaryComment"><param name="comp">The component associated with the</span>
/// message<span class="code-SummaryComment"></param></span>
/// <span class="code-SummaryComment"><param name="message">The status bar text for the</span>
/// component<span class="code-SummaryComment"></param></span>
public void SetStatusBarText(Component comp, string message)
{
    if(comp == null)
        throw new ArgumentException("Component cannot be null");

    MenuItem mi = comp as MenuItem;
    Control ctl = comp as Control;
    TabControl tc = comp as TabControl;

#if DOTNET_20
    ToolStripItem ti = comp as ToolStripItem;
    ToolStripControlHost tsch = comp as ToolStripControlHost;

    if(mi == null && ti == null && ctl == null)
#else
    if(mi == null && ctl == null)
#endif
        throw new ArgumentException(
            "Component must be a MenuItem, " +
            "ToolStripItem, or a Control");

    if(message != null && message.Length == 0)
        message = null;

If the hash table does not already contain the object, we create a new property object containing the message, and add it to the hash table using the object as the key. Then, based on the object type, we hook up one or more event handlers that will display the appropriate status bar text. This step is skipped at design-time though. For MenuItem objects, we hook up the Select event. For ToolStripItem objects, we hook up the MouseEnter and MouseLeave events. If the tool strip item is a ToolStripControlHost (i.e., it hosts a control such as a combo box or text box), we also hook up the Enter and Leave events so that status text is shown when tabbing into the control. For all other standard form controls, we hook up the GotFocus, Enter, and Leave events. Some controls such as Panel cannot receive focus but are entered, which is why both GotFocus and Enter are used.

If it is a tab control, we also have to hook up the SelectedIndexChanged event to allow displaying the status bar text for it and its pages. The tab control and tab pages do not reliably show their status bar text due to the way they handle the focus. As such, this event is needed to update the text. Note that it will not show the text if you use Shift+Tab to go from the first control on a tab back to the tab in the tab control itself, or when it is the first control to have the focus. You must also set ShowAsBlank or StatusBarText on the tab control itself if you want to have the status bar text appear for the tab pages themselves (i.e., when the tab itself has the focus).

if(!htOptions.Contains(comp))
{
    htOptions.Add(comp, new PropertyOptions(message));

    if(!this.DesignMode && message != null)
        if(mi != null)
            mi.Select += new EventHandler(Menu_Select);
        else
#if DOTNET_20
            if(ti != null)
            {
                ti.MouseEnter += new EventHandler(Control_Enter);
                ti.MouseLeave += new EventHandler(Control_Leave);

                // If it's a control host, hook the enter and
                // leave events too.
                if(tsch != null)
                {
                    tsch.Enter += new EventHandler(Control_Enter);
                    tsch.Leave += new EventHandler(Control_Leave);
                }
            }
            else
#endif
            {
                ctl.GotFocus += new EventHandler(Control_Enter);
                ctl.Enter += new EventHandler(Control_Enter);
                ctl.Leave += new EventHandler(Control_Leave);

                // See article notes above
                if(tc != null)
                    tc.SelectedIndexChanged += new EventHandler(
                        Control_Enter);
            }
}

If the object already exists in the hash table, we need to update the value in the existing property settings. In addition, if the property is cleared (i.e., set to a null or empty string), we need to disconnect the events. Again, this is skipped if it is done at design-time.

else
{
    PropertyOptions po = (PropertyOptions)htOptions[comp];
    po.Message = message;

    if(!this.DesignMode && message == null &&
      po.ShowAsBlank == false)
        if(mi != null)
            mi.Select -= new EventHandler(Menu_Select);
        else
#if DOTNET_20
            if(ti != null)
            {
                ti.MouseEnter -= new EventHandler(Control_Enter);
                ti.MouseLeave -= new EventHandler(Control_Leave);

                // If it's a control host, unhook the enter and
                // leave events too.
                if(tsch != null)
                {
                    tsch.Enter -= new EventHandler(Control_Enter);
                    tsch.Leave -= new EventHandler(Control_Leave);
                }
            }
            else
#endif
            {
                ctl.GotFocus -= new EventHandler(Control_Enter);
                ctl.Enter -= new EventHandler(Control_Enter);
                ctl.Leave -= new EventHandler(Control_Leave);

                if(tc != null)
                    tc.SelectedIndexChanged -= new EventHandler(
                        Control_Enter);
            }
}

The Menu Item Event Handlers

The event handlers are where most of the action takes place. For menu items, the Menu_Select event handles setting of the status bar text for the item. In addition, the first time it is called, it also hooks up an event handler on the parent form's MenuComplete event so that it can restore the text that was in the status bar prior to the item's text. The StatusBar, CurrentStatusBarText, ItemText, and StatusBarDefaultText properties are used to obtain references to the current status bar, its current text, the item's text, and the default status bar text based on the current settings (i.e., whether it is using the application status bar or an instance in a dialog box).

// This is handled to display status bar text for a MenuItem
// component.
private void Menu_Select(object sender, EventArgs e)
{
    if(this.StatusBar == null || !htOptions.Contains(sender))
        return;

    // Hook the MenuComplete event on first use to restore
    // the existing status bar text.
    if(!hookedMenuEvents)
    {
        Form frm = this.StatusBarParentForm;

        if(frm != null)
        {
            frm.MenuComplete += new EventHandler(
                Form_MenuComplete);
            hookedMenuEvents = true;
        }
    }

    this.CurrentStatusBarText = this.ItemText(sender);
}

// This is handled so that the old status bar text is restored
// when the component status bar text is no longer needed.
private void Form_MenuComplete(object sender, System.EventArgs e)
{
    if(this.StatusBar == null)
        return;

    this.CurrentStatusBarText = this.StatusBarDefaultText;
}

Other Control Event Handlers

For all other controls, the Control_Enter and Control_Leave events are used. On first use, the Control_Enter handler hooks up events on the parent form's Activated, Deactivated, and Closed events so that the existing status bar text can be restored.

// This is handled to display status bar text when a control
// is entered or gains the focus.
private void Control_Enter(object sender, EventArgs e)
{
    if(this.StatusBar == null || !htOptions.Contains(sender))
        return;

    // Hook the Closed event to reset the status bar text
    // when the form is closed. When it's modal, it doesn't
    // always get the Leave event to reset the text. The
    // Activated and Deactivated events are also hooked to
    // set and restore the text.
    if(!hookedFormEvent && this.StatusBar != null)
    {
        Control p = sender as Control;

        if(p != null)
            p = p.Parent;
#if DOTNET_20
        else    // It's a control hosted in a tool strip item
            p = ((ToolStripItem)sender).Owner.Parent;
#endif

        while(p != null)
        {
            Form frm = p as Form;

            if(frm != null)
            {
                frm.Activated += new EventHandler(
                    Form_Activated);

                // Same handler as Form.MenuComplete
                frm.Deactivate += new EventHandler(
                    Form_MenuComplete);
                frm.Closed += new EventHandler(
                    Form_MenuComplete);

                hookedFormEvent = true;
                break;
            }

            p = p.Parent;
        }
    }

    this.CurrentStatusBarText = this.ItemText(sender);
}

// This is handled to display status bar text when a control
// is left.
private void Control_Leave(object sender, EventArgs e)
{
    if(this.StatusBar == null || !htOptions.Contains(sender))
        return;

    this.CurrentStatusBarText = this.StatusBarDefaultText;
}

// This is handled to redisplay the status bar text for the
// form's focused control when activated.
private void Form_Activated(object sender, System.EventArgs e)
{
    Form frm = sender as Form;

    if(frm != null && this.StatusBar != null)
    {
        Control ctl = frm.ActiveControl;

        // Nested controls may not have any so walk up
        // the parent chain to see if they do.
        while(ctl != null && !htOptions.Contains(ctl))
            ctl = ctl.Parent;

        if(ctl != null)
            this.CurrentStatusBarText = this.ItemText(ctl);
    }
}

Demonstration Applications

A Windows Forms application in C# and VB.NET is provided that demonstrates the basic use of the status bar text provider. A version of each is provided for .NET 1.1 and .NET 2.0. The .NET 1.1 version demonstrates the use of the provider with menu items and with controls in modal and non-modal forms. The .NET 2.0 version demonstrates the use of the provider with menu strip, tool strip, and status strip items, along with standard controls in modal and non-modal forms. It also demonstrates the use of the extra StatusLabel and ProgressBar properties to access a status label and progress bar in the main status strip from within the demo dialog box form.

For either version, use the File | Load option to open non-modal instances of the demo form. Use the Help | About option to open a modal instance of the demo form. The demo form allows you to switch between using the application's status bar/status strip and the demo form's status bar for displaying the messages.

Revision History

06/26/2006 Added new overloaded static methods to the StatusBarTextProvider to make it easier to utilize the controls assigned to its StatusLabel and ProgressBar properties.
01/28/2006

Updated the component to support the new .NET 2.0 menu strip, tool strip, and status strip controls and their related tool strip item components.

Changed the data type on the ApplicationStatusBar and InstanceStatusBar properties to object to support specifying either a status bar object or a toolstrip item that will display the text. This change may break existing code if it relies on the data type being StatusBar as in the prior version.

Reworked how the prior text was restored due to the way the new tool strip components work. It now utilizes the new ApplicationDefaultText and InstanceDefaultText properties.

Added new StatusLabel and ProgressBar properties for use with .NET 2.0, to provide convenient access to the tool strip items they represent from anywhere within the application.

11/11/2005 Initial release

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Eric Woodruff
Software Developer (Senior)
United States United States
Eric Woodruff is an Analyst/Programmer for Spokane County, Washington where he helps develop and support various applications, mainly criminal justice systems, using Windows Forms (C#) and SQL Server as well as some ASP.NET applications.
 
He is also the author of some open source projects and shareware components for .NET including:
 
The Sandcastle Help File Builder - A front end and project management system that lets you build help file projects using Microsoft's Sandcastle documentation tools. It includes a standalone GUI and a package for Visual Studio integration.
 
Visual Studio Spell Checker - A Visual Studio editor extension that checks the spelling of comments, strings, and plain text as you type or interactively with a tool window. This can be installed via the Visual Studio Gallery.

Image Map Controls - Windows Forms and web server controls that implement image maps.
 
PDI Library - A complete set of classes that let you have access to all objects, properties, parameter types, and data types as defined by the vCard (RFC 2426), vCalendar, and iCalendar (RFC 2445) specifications. A recurrence engine is also provided that allows you to easily and reliably calculate occurrence dates and times for even the most complex recurrence patterns.
 
Windows Forms List Controls - A set of extended .NET Windows Forms list controls. The controls include an auto-complete combo box, a multi-column combo box, a user control dropdown combo box, a radio button list, a check box list, a data navigator control, and a data list control (similar in nature to a continuous details section in Microsoft Access or the DataRepeater from VB6).
 
For more information see http://www.EWoodruff.us

Comments and Discussions

 
GeneralToolStripMenuItems and Keyboard Access PinmemberStephen Baum26-Oct-07 2:46 
GeneralOutstanding PinmemberAreJay21-Sep-06 8:44 
GeneralGreat job PinmemberMahesh Sapre11-Jul-06 23:56 
GeneralRe: Great job PinmemberEric Woodruff12-Jul-06 17:02 
GeneralRe: Great job PinmemberMahesh Sapre12-Jul-06 19:00 
GeneralNice Job Pinmembersoloforce22-Feb-06 11:17 
GeneralGood! PinmemberDodgerSharp11-Nov-05 21:56 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140827.1 | Last Updated 7 Jul 2006
Article Copyright 2005 by Eric Woodruff
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid