Providing Feedback with Status Bars

Providing Feedback with Status Bars

Status bars are used to provide feedback in several ways. A common use for status bars is to provide additional descriptions of menu items as the user selects each item. Status bars often serve as dashboards, providing feedback about the current status of the application and computer.

Unlike the top-level menu discussed earlier in this chapter, in the section “Using a Main Menu with Forms,” a status bar doesn’t change the size of a form’s client area. Instead, the status bar control is placed on top of the form, as shown in Figure 13-6.

Figure 13-6.
A status bar control, which is placed above the form’s client area.

The distinction between reducing the size of the form and being placed on top of it is important if you’re working directly with the form surface, either by drawing on it, as will be discussed in Chapter 14, or by dynamically positioning controls.

Creating Status Bars

Status bars are created using the StatusBar class. A relatively small amount of code will create a simple but serviceable status bar, as shown here:

StatusBar status = new StatusBar();
Controls.Add(status);

This status bar will automatically dock itself to the bottom edge of its form, as its Dock property is, by default, set to DockStyle.Bottom. As mentioned, docking is simply a characteristic that specifies to which edge of the current form the control will attach itself; this feature will be discussed in more detail in Chapter 15.

When using a simple status bar, such as the one created in the preceding code fragment, a message can be displayed with the Text property, as shown here:

status.Text = "This is the status bar.";

By default, status bars include a sizing grip in the lower-right corner. A sizing grip simplifies the task of resizing a form because it increases the region that the user drags for resizing. Sometimes the sizing grip is undesirable, however, because it conflicts with other user interface elements (or maybe you just don’t like the sizing grip). You can control the visibility of the sizing grip with the Sizing­Grip property, as follows:

status.SizingGrip = false;

Although a status bar can be created using just source code, an easy way to add a status bar to a form is to use the Forms Designer. When a form is open in the Forms Designer, the Toolbox includes a status bar control. When you add a status bar control to a form, the following properties are set by default:

  • The Dock property is set to DockingStyle.Bottom.

  • The SizingGrip property is set to true.

  • The Text property is set to the name of the control.

If your application has a menu, it’s traditional to provide an option for users to hide user interface elements such as status bars. Like most controls, the StatusBar class exposes the Visible property, which hides the status bar when set to false, as shown here:

status.Visible = false;

You can also use the Visible property to determine the current state of the status bar, as follows:

if(status.Visible == false)
{
    
    
Using Status Bar Panels

A common way to use a status bar is to segment the display area into multiple panels, with each panel used for a specific type of information. Each panel can be updated separately, and often each has its own display characteristics. Typically, panels that are dedicated to a specific type of information—such as the status of locking keyboard keys, the time, or other status information—have a three-dimensional, sunken style. Panels that provide general feedback text—such as descriptions of selected menu items—are often drawn in a flat style.

The StatusBarPanels class represents the panels displayed on a status bar. The most commonly used StatusBarPanel properties are as follows:

  • Alignment  A value from the HorizontalAlignment enumeration that specifies how items are aligned in the panel.

  • AutoSize  A value from the StatusBarPanelAutoSize enumeration that specifies how the panel handles automatic sizing.

  • BorderStyle  A value from the StatusBarBorderStyle enumeration that specifies the panel’s border.

  • MinWidth  The minimum width for the panel. If the AutoSize property is set to None, this property is automatically set equal to the Width property. For other AutoSize scenarios, the value of this property is used to ensure a minimum usable size for the panel.

  • Style  Specifies whether the panel is drawn by the .NET Framework or by the owner of the control. By default, this property is set to Status­BarPanelStyle.Text, causing the panel to be drawn by the .NET Framework. To take control over drawing the panel, set this property to StatusBarPanelStyle.OwnerDraw.

  • Text  The message displayed in the panel.

  • Width  The width of the panel.

Values from the HorizontalAlignment enumeration are provided in Table 13-17. The default value for StatusBar objects is HorizontalAlignment.Left.

Values from the StatusBarPanelAutoSize enumeration are provided in Table 13-18. The default value is StatusBarPanelAutoSize.None. Using panels that support automatic sizing is discussed later in this section.

Table 13-18.  StatusBarPanelAutoSize Enumeration Values 

Value

Description

None

No auto-sizing is done; the width of the panel is specified by the Width property.

Contents

The width of the panel is auto-sized to fit its contents.

Spring

The panel expands to fill space not taken up by other panels. All panels that have their AutoSize property set to Spring will share the available space.

Values from the StatusBarPanelBorderStyle enumeration are provided in Table 13-19. The default value for BorderStyle is StatusBarPanelBorderStyle.None.

Each status bar maintains a collection of the StatusBarPanel objects it owns; this collection is accessible through the Panels property. The Panels property returns a reference to a StatusBarPanelCollection object, which is typically used directly, just like the MenuItemCollection class discussed earlier in this chapter, in the section “Creating a Menu Programmatically.” For example, to add a panel to a status bar, you can use code like this:

StatusBarPanel mainPanel = new StatusBarPanel();
status.Panels.Add(mainPanel); 

To remove a panel, use the collection’s Remove or RemoveAt properties, as shown here:

status.Panels.Remove(mainPanel);
status.Panels.RemoveAt(0);

The StatusBarPanelCollection class exposes an indexer, which enables you to use the Panels property as an array of StatusBarPanel objects, like this:

foreach(StatusBarPanel panel in status.Panels)
{
    panel.AutoSize = StatusBarPanelAutoSize.Contents;
}
status.Panels[0].AutoSize = StatusBarPanelAutoSize.Spring;
status.Panels[0].BorderStyle = StatusBarPanelBorderStyle.None;
status.Panels[1].BorderStyle = StatusBarPanelBorderStyle.Sunken;

The StatusBar class exposes the ShowPanels property, which is used to enable the display of status bar panels and is set to false by default. The following code enables the use of panels, creates two status bar panels, and adds them to the status bar:

StatusBar status = new StatusBar();
status.ShowPanels = true;
StatusBarPanel mainPanel = new StatusBarPanel();
StatusBarPanel timePanel = new StatusBarPanel();
status.Panels.Add(mainPanel);
status.Panels.Add(timePanel); 

Visual C# .NET includes the StatusBarPanel Collection Editor, which can be used to easily manage status bar panels. You can launch this editor by clicking the button adjacent to the Panels property in the Properties window. Initially, the editor is empty, as shown in Figure 13-7.

Figure 13-7.
The StatusBarPanel Collection Editor before any panels have been added.

Panels are added to the status bar’s collection of panels by clicking the Add button. After a panel is added to the collection, its properties can be managed from within the editor. A list of the panels in the collection is provided on the left side of the editor, and the selected panel’s properties are displayed on the right, as shown in Figure 13-8.

Figure 13-8.
Editing status bar panels using the StatusBarPanel Collection Editor.

The size of each panel in the status bar depends on several factors—primarily, the value of each panel’s AutoSize and Width properties. Taken together, these properties enable panels to be sized in a cooperative way, and in many cases there’s no need to specify an explicit size for status bar panels. The status bar adjusts the width of its panels using the following rules:

  • Any panels that have their AutoSize property set to StatusBarPanel­AutoSize.None will be sized according to their Width property.

  • Any panels that have their AutoSize property set to StatusBarPanel­AutoSize.Contents will have their width set to a size large enough to display their contents, but not less than their MinWidth property.

  • Any panels that have their AutoSize property set to StatusBarPanel­AutoSize.Spring will divide the remaining space on the status bar.

When a status bar is too small to display all panels, the panels are displayed in the order in which they were stored in the status bar’s collection of panels.

Displaying the Time and Date

The companion CD includes an example project named StatusBars that creates a status bar with two panels, shown in Figure 13-9: one panel for menu help text, and another panel that displays the time.

Figure 13-9.
The StatusBars example project.

Three controls have been added to the main form in the StatusBars project:

  • A MainMenu control is used to display commands available to the user.

  • A Timer control is used to generate timer events at 10-second intervals so that the time on the status bar can be updated.

  • A StatusBar control with two panels is used to provide feedback to the user.

The first status bar panel is named helpPanel and is used to display help text for menu items selected by the user. Its AutoSize property is set to StatusBarPanelAutoSize.Spring to enable it to grow to the maximum available size. The second status bar panel is named timePanel and is used to display the current time. Its AutoSize property is set to StatusBarPanelAutoSize.Contents, which properly sizes the panel to contain the current time.

Updating the Status Bar for Menu Events

As mentioned, a Select event is raised for each menu item selected by the user. The StatusBars application displays help text for each menu item by implementing handlers for these events, as shown here:

private void fileMenuItem_Select(object sender, System.EventArgs e)
{
    helpPanel.Text = "File Menu";
}

private void openMenuItem_Select(object sender, System.EventArgs e)
{
    helpPanel.Text = "Open file for editing";
}

private void closeMenuItem_Select(object sender, System.EventArgs e)
{
    helpPanel.Text = "Close the current file";
}

private void exitMenuItem_Select(object sender, System.EventArgs e)
{
    helpPanel.Text = "Exit the application";
}

private void statusBarMenuItem_Select(object sender, System.EventArgs e)
{
    helpPanel.Text = "Toggle the status bar";
}

These events aren’t sufficient to properly update the status bar because the status bar would always contain the help text for the last menu item that was selected. To clear the status bar after an item has been selected or the menu has been dismissed, the StatusBars application provides a handler for the form’s MenuComplete event, as follows:

private void MainForm_MenuComplete(object sender, System.EventArgs e)
{
    helpPanel.Text = "";
}
Displaying the Time in the Status Bar

The time panel in the status bar is refreshed periodically based on a timer control on the main form. Each time the timer raises a Tick event, it’s handled by the StatusBars application’s main form, as shown here:

private void timer_Tick(object sender, System.EventArgs e)
{
    timePanel.Text = DateTime.Now.ToShortTimeString();
}

For each Tick event that’s raised, the current time is retrieved through the Now static property exposed by the DateTime class. This property returns a DateTime object, which is then converted to a string with the ToShortTimeString method.



Part III: Programming Windows Forms