The Status Bar

The status bar window neither accepts user input nor generates command messages. Its job is simply to display text in panes under program control. The status bar supports two types of text panes—message line panes and status indicator panes. To use the status bar for application-specific data, you must first disable the standard status bar that displays the menu prompt and key-board status.

The Status Bar Definition

The static indicators array that AppWizard generates in the MainFrm.cpp file defines the panes for the application's status bar. The constant ID_SEPARATOR identifies a message line pane; the other constants are string resource IDs that identify indicator panes. Figure 14-3 shows the indicators array and its relationship to the standard framework status bar.

Click to view at full size.

Figure 14-3. The status bar and the indicators array.

The CStatusBar::SetIndicators member function, called in the application's derived frame class, configures the status bar according to the contents of the indicators array.

The Message Line

A message line pane displays a string that the program supplies dynamically. To set the value of the message line, you must first get access to the status bar object and then you must call the CStatusBar::SetPaneText member function with a zero-based index parameter. Pane 0 is the leftmost pane, 1 is the next pane to the right, and so forth.

The following code fragment is part of a view class member function. Note that you must navigate up to the application object and then back down to the main frame window.

CMainFrame* pFrame = (CMainFrame*) AfxGetApp()->m_pMainWnd;
CStatusBar* pStatus = &pFrame->m_wndStatusBar;
pStatus->SetPaneText(0, "message line for first pane");

Normally, the length of a message line pane is exactly one-fourth the width of the display. If, however, the message line is the first (index 0) pane, it is a stretchy pane without a beveled border. Its minimum length is one-fourth the display width, and it expands if room is available in the status bar.

The Status Indicator

A status indicator pane is linked to a single resource-supplied string that is displayed or hidden by logic in an associated update command UI message handler function. An indicator is identified by a string resource ID, and that same ID is used to route update command UI messages. The Caps Lock indicator is handled in the frame class by a message map entry and a handler function equivalent to those shown below. The Enable function turns on the indicator if the Caps Lock mode is set.

ON_UPDATE_COMMAND_UI(ID_INDICATOR_CAPS, OnUpdateKeyCapsLock)

void CMainFrame::OnUpdateKeyCapsLock(CCmdUI* pCmdUI)
{
    pCmdUI->Enable(::GetKeyState(VK_CAPITAL) & 1);
}

The status bar update command UI functions are called during idle processing so that the status bar is updated whenever your application receives messages.

The length of a status indicator pane is the exact length of the corresponding resource string.

Taking Control of the Status Bar

In the standard application framework implementation, the status bar has the child window ID AFX_IDW_STATUS_BAR. The application framework looks for this ID when it wants to display a menu prompt. The update command UI handlers for the keyboard state indicators, embedded in the frame window base class, are linked to the following string IDs: ID_INDICATOR_CAPS, ID_INDICATOR_NUM, and ID_INDICATOR_SCRL. To take control of the status bar, you must use a different child window ID and you must use different indicator ID constants.

The only reason to change the status bar's child window ID is to prevent the framework from writing menu prompts in pane 0. If you like the menu prompts, you can disregard the following instructions.

The status bar window ID is assigned in the CStatusBar::Create function called by the derived frame class OnCreate member function. That function is contained in the MainFrm.cpp file that AppWizard generates. The window ID is the third Create parameter, and it defaults to AFX_IDW_STATUS_BAR.

To assign your own ID, you must replace this call

m_wndStatusBar.Create(this);

with this call

m_wndStatusBar.Create(this, WS_CHILD | WS_VISIBLE | CBRS_BOTTOM, 
                      ID_MY_STATUS_BAR);

You must also, of course, define the ID_MY_STATUS_BAR constant in the resource.h file (using Visual C++'s resource symbol editor).

We forgot one thing. The standard application framework's View menu allows the user to turn the status bar on and off. That logic is pegged to the AFX_IDW_STATUS_BAR window ID, so you'll have to change the menu logic, too. In your derived frame class, you must write message map entries and handlers for the ID_VIEW_STATUS_BAR command and update command UI messages. ID_VIEW_STATUS_BAR is the ID of the Status Bar menu item. The derived class handlers override the standard handlers in the CFrameWnd base class. See the EX14B example for code details.