Status bars can provide additional information about your program, as well as to add controls to the bottom of your form for informational display. A status bar consists of a number of Panels (each of which may contain other controls), and you can display information directly on the status bar itself.
In the next example, you will modify the previous example to add a status bar that will display both the current time and the amount of time the application has been running, as shown in Figure 18-23.
Figure 18-24. Status bar demonstration
In addition, when you click on or hover over menu choices, the time panels will disappear and information about the menu choice will be displayed, as shown in Figure 18-24.
Figure 18-25. Hiding the panels
To add some spice to this application, when you left-click on the status bar, the elapsed timer will be reset to zero, and when you right-click on the status bar, a context menu will pop up, offering to reset, suspend, or resume the timer as shown in Figure 18-25.
Figure 18-26. Pop-up menu
|
18.5.1 Analysis
First, add a StatusBar object to your form. Notice that when you drag this object onto your form, it adheres to the form (unlike the Menu, which must be set as a property of the form). This is just Visual Studio .NET's way of keeping life interesting.
The StatusBar object itself has a great many properties, methods, and events, most inherited from Control. Some of the most important properties are shown in Table 18-9.
Property |
Type |
Description |
---|---|---|
Dock |
DockStyle |
Read/Write. DockStyle is an Enumeration (Bottom, Fill, Left, None, Right, Top) that determines how the status bar is docked to the form. |
Panels |
StatusPanelCollection |
Read-only. The collection of Panels in the status bar. |
ShowPanels |
Boolean |
Read/Write. If true, the panels are displayed: otherwise, the Text property is displayed. The default is false. |
SizingGrip |
Boolean |
Read/Write. If true (the default), a sizing grip is displayed in the lower-right corner of the status bar. |
Text |
String |
Text that is displayed if the ShowPanels property is set to false. |
Your first task is to add a couple of panels to the status bar. In this case, you'll want three. One will hold the place for the menu information, and the other two will be for the time and elapsed time, respectively.
Status bar panels are encapsulated in the StatusBarPanel class, which also has several useful properties. These properties will be discussed next when you create the Panels.
Navigate to the Panels (Collection) property and click on the button to open the StatusBarPanel Collection Editor. Click Add to add your first panel, which you will name pnlMenuHelp. Set the AutoSize property of this panel to Spring. This property is an enumeration of type StatusBarPanelAutoSize, whose three possible values are shown in Table 18-10.
Value |
Description |
---|---|
Contents |
The width is determined by the contents. |
None |
The panel does not change size when the status bar control resizes. |
Spring |
The panel shares available space within the status bar with other properties set to Spring. |
The complete set of properties to set is shown in Figure 18-26.
Figure 18-27. Properties for pnlMenuHelp
The second panel you need to add is for the current time. Its properties are shown in Figure 18-27.
Figure 18-28. pnlCurrentTime properties
Notice that this panel has its Alignment set to Center (so that the time is centered) and its Border style set to Sunken. In addition, the AutoSize property is set to Contents so that the panel will be sized to the display string.
Finally, add a third panel for the Elapsed time, as shown in Figure 18-28, noting the minor differences from the CurrentTime panel. Notice that the ToolTipText for this panel is "Time you've had this application open".
Figure 18-29. Elapsed time panel
If you run the application now, you'll find that the status bar displays only "StatusBar1" and no panels are visible. Back in design mode, click on the status bar and set the ShowPanels property to true. Run the application and the panels display, but the time is not shown and clicking on the panel does nothing.
18.5.1.1 Setting the timer
To get the panels to display the current and elapsed time, you'll need a timer, as described in Chapter 1. Add a timer to the form, and then set the timer in the +constructor:
timer1.Interval = 1000; timer1.Start( );
This creates a timer that will fire an event every second (the Interval property is in milliseconds).
You'll also need a private member variable to keep track of the starting time (to display elapsed time):
private DateTime startTime;
Private startTime As DateTime
In your constructor, you'll initialize the startTime member variable with the current time:
startTime = DateTime.Now;
The Timer will fire the Tick event. Double-click on the timer in your designer to set up the event handler. In the event handler, you'll want to do two things. First, set the panel for the current time to the current time:
private void timer1_Tick(object sender, System.EventArgs e) { pnlCurrentTime.Text = DateTime.Now.ToLongTimeString( );
Second, compute the elapsed time, and then display it in the panel for the elapsed time:
TimeSpan elapsedSpan = DateTime.Now - this.startTime; DateTime elapsed = DateTime.Parse(elapsedSpan.ToString( )); pnlElapsedTime.Text = "Elapsed: " + elapsed.ToString("HH:mm:ss"); }
Private Sub Timer1_Tick( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles Timer1.Tick pnlCurrentTime.Text = DateTime.Now.ToLongTimeString( ) Dim elapsedSpan As TimeSpan = (DateTime.Now).Subtract(Me.startTime) Dim elapsed As DateTime = DateTime.Parse(elapsedSpan.ToString( )) pnlElapsedTime.Text = "Elapsed: " + elapsed.ToString("HH:mm:ss") End Sub
If you run the application now, your panels will be updated.
18.5.1.2 Updating the status bar based on menu information
You'll want to hide the panels when the user clicks on a menu choice. That is easy to do if you know when the user has begun clicking on menu items and when the user has finished. The form itself has two events to which you can respond: MenuStart and MenuComplete. You need write only the event handlers:
private void OnMenuStart(object sender, System.EventArgs e) { statusBar1.ShowPanels = false; } private void OnMenuComplete(object sender, System.EventArgs e) { statusBar1.ShowPanels = true; }
Private Sub Form1_MenuStart( _ ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles MyBase.MenuStart StatusBar1.ShowPanels = False End Sub Private Sub Form1_MenuComplete( _ ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles MyBase.MenuComplete StatusBar1.ShowPanels = True End Sub
|
When the user actually does highlight on a menu choice, update the information in the status bar for that MenuItem. Each MenuItem has a Select event, and there is no reason not to use a common event handler for this event. In a sophisticated program, you will want to determine which menu choice the user is considering and provide meaningful help, but for now you can stub out the event handler:
private void OnMenuSelect(object sender, System.EventArgs e) { MenuItem mi = (MenuItem) sender; statusBar1.Text = "Information here about " + mi.Text; }
Private Sub OnMenuSelect( _ ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles mnuFile.Select, mnuFileOpen.Select, mnuFileClose.Select, _ mnuFileSave.Select, mnuFileSaveAs.Select, mnuEdit.Select, _ mnuEditCopy.Select, mnuEditPaste.Select, mnuOption1.Select, _ mnuOption2.Select, mnuOption3.Select, mnuOptions.Select, _ mnuRadioOptions.Select, mnuRadioOption1.Select, _ mnuRadioOption2.Select, mnuRadioOption3.Select, mnuSpecial.Select, _ mnuODVote.Select, mnuODShazam.Select, mnuMerge.Select, _ mnuMenu1.Select, mnuMenu11.Select, mnuMenu12.Select, _ mnuMenu13.Select, mnuMenu14.Select, mnuMenu2.Select, _ mnuMenu21.Select, mnuMenu22.Select, _ mnuMenu23.Select, mnuMenu24.Select, mnuWindow.Select Dim mi As MenuItem = CType(sender, MenuItem) StatusBar1.Text = "Information here about " + mi.Text End Sub
18.5.1.3 Handling status bar events
The status bar itself has several events to which you might want to respond. The default event is PanelClick. In this example, you'll implement an event handler to test which button the user has pressed if it is the right button, you'll zero the elapsed timer. This is facilitated by the StatusBarPanelClickEventArgs parameter passed into the event handler, which can, among other things, provide access to the mouse button that was clicked:
private void statusBar1_PanelClick( object sender, System.Windows.Forms.StatusBarPanelClickEventArgs e) { if ( e.Button. = = MouseButtons.Left) { startTime = DateTime.Now; } }
Private Sub StatusBar1_PanelClick( _ ByVal sender As System.Object, _ ByVal e As System.Windows.Forms.StatusBarPanelClickEventArgs) _ Handles StatusBar1.PanelClick If e.Button = MouseButton.Left Then startTime = DateTime.Now End If End Sub
18.5.1.4 Adding a context menu
Finally, to handle the right mouse button, you'll add a context menu. Do so as described earlier in Section 18.2.9, by adding three entries: Reset Time, Suspend Time, and Resume Time. Name the context menu pnlContextMenu, and assign it to the ContextMenu property of the status bar, either in the properties window as shown in Figure 18-29 or, if you prefer, programmatically in the constructor.
public Form1( ) { InitializeComponent( ); timer1.Interval = 1000; timer1.Start( ); startTime = DateTime.Now; statusBar1.ContextMenu = pnlContextMenu;
Add three menu items to the context menu: Reset Time, Suspend Time, and Resume Time.
Figure 18-30. Adding the context menu
|
In either case, you now must implement the three event handlers:
private void MnuResetTime_Click(object sender, System.EventArgs e) { startTime = DateTime.Now; } private void mnuSuspendTime_Click(object sender, System.EventArgs e) { timer1.Stop( ); } private void mnuResumeTime_Click(object sender, System.EventArgs e) { timer1.Start( ); }
Private Sub mnuResetTime_Click( _
ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles mnuResetTime.Click startTime = DateTime.Now End Sub Private Sub mnuSuspendTime_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles mnuSuspendTime.Click Timer1.Stop( ) End Sub Private Sub mnuResumeTime_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles mnuResumeTime.Click Timer1.Start( ) End Sub
Windows Forms and the .NET Framework
Getting Started
Visual Studio .NET
Events
Windows Forms
Dialog Boxes
Controls: The Base Class
Mouse Interaction
Text and Fonts
Drawing and GDI+
Labels and Buttons
Text Controls
Other Basic Controls
TreeView and ListView
List Controls
Date and Time Controls
Custom Controls
Menus and Bars
ADO.NET
Updating ADO.NET
Exceptions and Debugging
Configuration and Deployment