| Tenouk | Home | Toolbars, Status Bars and ReBar 1 | Toolbars, Status Bars and ReBar 3 | Download | Site Index |


 

 

 

 

 

Module 8a:

Toolbars, Status Bars and ReBar 2

 

 

 

 

 

This is a continuation from the previous module... Program examples compiled using Visual C++ 6.0 (MFC 6.0) compiler on Windows XP Pro machine with Service Pack 2. Topics and sub topics for this Tutorial are listed below:

  1. The Status Bar

  2. The Status Bar Definition

  3. The Message Line

  4. The Status Indicator

  5. Taking Control of the Status Bar

  6. The MYMFC12 Status Bar Example

 

 

 

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 shows the indicators array and its relationship to the standard framework status bar.

 

 

Figure 14: 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 MYMFC12 example for code details.

 

The MYMFC12 Status Bar Project Example

 

The MYMFC12 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

 

Table 5

 

The resulting status bar is shown in Figure 15. Notice that the leftmost pane stretches past its normal 1/20-screen length as the displayed frame window expands.

 

The status bar of the MYMFC12 example.

 

Figure 15: The status bar of the MYMFC12 example.

 

Follow these steps to produce the MYMFC12 example:

 

Run AppWizard to generate \mfcproject\mymfc12. Accept all default settings but two: select Single Document and deselect Printing and Print Preview and ActiveX Controls. The options and the default class names are shown here.

 

MYMFC12 project summary.

 

Figure 16: MYMFC12 project summary.

 

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. Double-click on the String Table icon in the String Table folder on the ResourceView page to bring up the string editor. Then, double-click on the empty entry at the end of the list. A dialog allows you to assign the ID and the string value as shown below.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Using string editor to add and edit new string.

 

Figure 17: Using string editor to add and edit new string.

 

Add two strings as follows.

 

String ID

String Caption

ID_INDICATOR_LEFT

LEFT

ID_INDICATOR_RIGHT

RIGHT

 

Table 6

 

Use Visual C++ to edit the application's symbols. Choose Resource Symbols from the View menu. Add the new status bar identifier, ID_MY_STATUS_BAR, and accept the default value.

 

Using Resource Symbol dialog to add new status bar identifier, ID_MY_STATUS_BAR.

 

Figure 18: Using Resource Symbol dialog to add new status bar identifier, ID_MY_STATUS_BAR.

 

Use ClassWizard to add View menu command handlers in the class CMainFrame. 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()

 

Table 7

 

Adding View menu command handlers in the class CMainFrame.

 

Figure 19: Adding View menu command handlers in the class CMainFrame.

 

Add the following function prototypes to MainFrm.h. You must add these CMainFrame message handler prototypes manually because ClassWizard doesn't recognize the associated command message IDs.

 

afx_msg void OnUpdateLeft(CCmdUI* pCmdUI);

afx_msg void OnUpdateRight(CCmdUI* pCmdUI);

 

Visual C++ code segment

 

Listing 10.

 

Add the message handler statements inside the AFX_MSG brackets so that ClassWizard will let you access and edit the code later. While MainFrm.h is open, make m_wndStatusBar public rather than protected.

 

Visual C++ code segment

 

Listing 11.

 

Edit the MainFrm.cpp file. Replace the original indicators array with the following code:

 

static UINT indicators[] =

{

    ID_SEPARATOR,  // first message line pane

    ID_SEPARATOR,  // second message line pane

    ID_INDICATOR_LEFT,

    ID_INDICATOR_RIGHT,

};

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

------------------------------------------------------------------------------------------------------------------------------------

 

Visual C++ code segment

 

Listing 12.

 

Next edit the OnCreate() member function. Replace the following statement:

 

if (!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

}

 

Visual C++ code segment

 

Listing 13.

 

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. ClassWizard 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)

 

Visual C++ code segment

 

Listing 14.

 

Next 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);

}

 

Visual C++ code segment

 

Listing 15.

 

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 that ClassWizard originally generated in MainFrm.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);

}

 

Visual C++ code segment

 

Listing 16.

 

These functions ensure that the View menu Status Bar command is properly linked to the new status bar. Edit the OnDraw() function in Mymfc12View.cpp. The OnDraw() function displays a message in the view window. Add the following code:

 

void CMymfc12View::OnDraw(CDC* pDC)

{

    pDC->TextOut(30, 30, "Watch the status bar while you move and click the mouse.");

}

 

Visual C++ code segment

 

Listing 17.

 

Add a WM_MOUSEMOVE handler in the CMymfc12View class. Use ClassWizard to map the message to OnMouseMove() and then 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.

 

Adding a WM_MOUSEMOVE handler in the CMymfc12View class.

 

Figure 20: Adding a WM_MOUSEMOVE handler in the CMymfc12View class.

 

void CMymfc12View::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);

    }

}

 

Visual C++ code segment

 

Listing 18.

 

Finally, add the include statement:

 

#include "MainFrm.h"

 

Near the top of the file mymfc12View.cpp.

 

Visual C++ code segment

 

Listing 19.

 

Build and test the MYMFC12 application. Move the mouse, and observe that the left 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?

 

MYMFC12 program output with new status bar items.

 

Figure 21: MYMFC12 program output with new status bar items.

 

 

Disabling the status bar.

 

Figure 22: Disabling the status bar.

 

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 their 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);

 

Visual C++ code segment

Listing 20.

 

MYMFC12 with new status bar modification.

 

Figure 23: MYMFC12 with new status bar modification.

 

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.

 

 

Continue on next module...part 3.

 

 

 

 

Further reading and digging:

  1. MSDN MFC 7.0 class library online documentation.

  2. MSDN MFC 9.0 class library online documentation - latest version.

  3. Porting & Migrating your older programs.

  4. MSDN Library

  5. DCOM at MSDN.

  6. COM+ at MSDN.

  7. COM at MSDN.

  8. Windows data type.

  9. Win32 programming Tutorial.

  10. The best of C/C++, MFC, Windows and other related books.

  11. Unicode and Multibyte character set: Story and program examples.

 

 

 

 


 

| Tenouk | Home | Toolbars, Status Bars and ReBar 1 | Toolbars, Status Bars and ReBar 3 | Download | Site Index |