The Ex13b Example: Using Status Bars
The Ex13b example replaces the standard application framework status bar with a new status bar that has the following text panes:
Pane Index | String ID | Type | Description |
---|---|---|---|
0 | ID_SEPARATOR (0) | Message line | x cursor coordinate |
1 | ID_SEPARATOR (0) | Message line | y cursor coordinate |
2 | ID_INDICATOR_LEFT | Status indicator | Left mouse button status |
3 | ID_INDICATOR_RIGHT | Status indicator | Right mouse button status |
The resulting status bar is shown in Figure 13-4. Notice that the leftmost pane stretches past its normal screen length as the displayed frame window expands.

Figure 13-4: The status bar of the Ex13b example.
Follow these steps to produce the Ex13b example:
Run the MFC Application Wizard to generate a project named Ex13b. Choose New Project from Visual Studio's File menu. In the New Project dialog box, select the MFC Application template, type the name Ex13b, and click OK. In the MFC Application Wizard, accept all the defaults but two: On the Application Type page, select Single Document, and on the Advanced Features page, deselect Printing And Print Preview.
Use the string editor to edit the application's string table resource. The application has a single string table resource with artificial "segment" divisions left over from the 16-bit era. In Resource View, double-click on the String Table icon in the String Table folder to bring up the string editor. Then select the empty entry at the end of the list and add the following two strings:
String ID
String Caption
ID_INDICATOR_LEFT
LEFT
ID_INDICATOR_RIGHT
RIGHT
When you're finished, the string table should appear as follows:
Edit the application's symbols. Choose Resource Symbols from the Edit menu. Click the New button and add the new status bar identifier, ID_MY_STATUS_BAR, and accept the default value as shown here:
Add View menu command handlers in the class CmainFrame. Select the CMainFrame class in Class View, click the Events button in the Properties window, and add the following command message handlers:
Object ID
Message
Member Function
ID_VIEW_STATUS_BAR
COMMAND
OnViewStatusBar
ID_VIEW_STATUS_BAR
UPDATE_COMMAND_UI
OnUpdateViewStatusBar
Add the following function prototypes toMainFrm.h . You must add these CMainFrame message handler prototypes manually because Visual Studio doesn't recognize the associated command message IDs.
afx_msg void OnUpdateLeft(CCmdUI* pCmdUI);
afx_msg void OnUpdateRight(CCmdUI* pCmdUI);
WhileMainFrm.h is open, make m_wndStatusBar public rather than protected.
Edit theMainFrm.cpp file. Replace the original indicators array with the following boldface code:
static UINT indicators[] =
{
ID_SEPARATOR, // first message line pane
ID_SEPARATOR, // second message line pane
ID_INDICATOR_LEFT,
ID_INDICATOR_RIGHT,
};
Next, edit the OnCreate member function. Replace the following statementif (!m_wndStatusBar.Create(this) ||
!m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
{
TRACE0("Failed to create status bar\n");
return -1; // fail to create
}
with the statement shown here:if (!m_wndStatusBar.Create(this,
WS_CHILD | WS_VISIBLE | CBRS_BOTTOM, ID_MY_STATUS_BAR) ||
!m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
{
TRACE0("Failed to create status bar\n");
return -1; // fail to create
}
The modified call to Create uses our own status bar ID, ID_MY_STATUS_BAR, instead of AFX_IDW_STATUS_BAR (the application framework's status bar object).Now add the following message map entries for the class CMainFrame. Visual Studio can't add these for you because it doesn't recognize the string table IDs as object IDs.
ON_UPDATE_COMMAND_UI(ID_INDICATOR_LEFT, OnUpdateLeft)
ON_UPDATE_COMMAND_UI(ID_INDICATOR_RIGHT, OnUpdateRight)
Add the following CMainFrame member functions that update the two status indicators:
void CMainFrame::OnUpdateLeft(CCmdUI* pCmdUI)
{
pCmdUI->Enable(::GetKeyState(VK_LBUTTON) < 0);
}
void CMainFrame::OnUpdateRight(CCmdUI* pCmdUI)
{
pCmdUI->Enable(::GetKeyState(VK_RBUTTON) < 0);
}
Note that the left and right mouse buttons have virtual key codes like keys on the keyboard have. You don't have to depend on mouse-click messages to determine the button status.Finally, edit the following View menu functions inMainFrm.cpp :
void CMainFrame::OnViewStatusBar()
{
m_wndStatusBar.ShowWindow((m_wndStatusBar.GetStyle() &
WS_VISIBLE) == 0);
RecalcLayout();
}
void CMainFrame::OnUpdateViewStatusBar(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck((m_wndStatusBar.GetStyle() & WS_VISIBLE) != 0);
}
These functions ensure that the View menu's Status Bar command is properly linked to the new status bar.
Edit the OnDraw function inEx13bView.cpp . The OnDraw function displays a message in the view window. Add the following boldface code:
void CEx13bView::OnDraw(CDC* pDC)
{
CEx13bDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
pDC->TextOut(0, 0,
"Watch the status bar while you move and click the mouse.");
}
Add a WM_MOUSEMOVE handler in the CEx13bView class. Select the CEx13bView class in Class View, click the Messages button in the Properties window, and add the OnMouseMove function. Edit the function as shown below. This function gets a pointer to the status bar object and then calls the SetPaneText function to update the first and second message line panes.void CEx13bView::OnMouseMove(UINT nFlags, CPoint point)
{
CString str;
CMainFrame* pFrame = (CMainFrame*) AfxGetApp()->m_pMainWnd;
CStatusBar* pStatus = &pFrame->m_wndStatusBar;
if (pStatus) {
str.Format("x = %d", point.x);
pStatus->SetPaneText(0, str);
str.Format("y = %d", point.y);
pStatus->SetPaneText(1, str);
}
}
Finally, add the statement
#include "MainFrm.h"
near the top of the fileEx13bView.cpp .
Build and test the Ex13b application. Move the mouse and observe that the first two status bar panes accurately reflect the mouse cursor's position. Try the left and right mouse buttons. Can you toggle the status bar on and off from the View menu?Note
If you want the first (index 0) status bar pane to have a beveled border like the other panes and you want the status bar to grow and resize to fit the contents, include the following two lines in the CMainFrame::OnCreate function, following the call to the status bar Create function.m_wndStatusBar.SetPaneInfo(0, 0, 0, 50);
m_wndStatusBar.SetPaneInfo(1, 0, SBPS_STRETCH, 50);
These statements change the width of the first two panes (from their default of one-fourth the display size) and make the second pane (index 1) the stretchy one.