| Tenouk C & C++ | MFC Home | Menus, Key Acc., Rich Edit & Property Sheets 4 | Toolbars, Status Bars and ReBar 2 | Download | Site Index |


 

 

 

 

 

Module 8:

Toolbars, Status Bars and ReBar 1

 

 

 

 

 

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. Toolbars and Status Bars

  2. Control Bars and the Application Framework

  3. The Toolbar

  4. The Toolbar Bitmap

  5. Button States

  6. The Toolbar and Command Messages

  7. Toolbar Update Command UI Message Handlers

  8. ToolTips

  9. Locating the Main Frame Window

  10. The MYMFC11 Toolbar Example

  11. Bitmap Image example

 

 

 

Toolbars and Status Bars

 

All the Microsoft Visual C++ examples up to this point have included toolbars and status bars. AppWizard generated the code that initialized these application framework elements as long as you accepted the AppWizard default options Docking Toolbar and Initial Status Bar. The default toolbar provides graphics equivalents for many of the standard application framework menu selections, and the default status bar displays menu prompts together with the keyboard state indicators CAP, NUM, and SCRL.

This module shows you how to customize the toolbar and the status bar for your application. You'll be able to add your own toolbar graphical buttons and control their appearance. You'll also learn how to disable the status bar's normal display of menu prompts and keyboard indicators. This allows your application to take over the status bar for its own use.

 

Control Bars and the Application Framework

 

The toolbar is an object of class CToolBar, and the status bar is an object of class CStatusBar. Both these classes are derived from class CControlBar, which is itself derived from CWnd. The CControlBar class supports control bar windows that are positioned inside frame windows. These control bar windows resize and reposition themselves as the parent frame moves and changes size. The application framework takes care of the construction, window creation, and destruction of the control bar objects. AppWizard generates control bar code for its derived frame class located in the files MainFrm.cpp and MainFrm.h.

In a typical SDI application, a CToolBar object occupies the top portion of the CMainFrame client area and a CStatusBar object occupies the bottom portion. The view occupies the remaining (middle) part of the frame.

Beginning with MFC Library version 4.0, the toolbar has been built around the toolbar common control that first became available with Microsoft Windows 95. Thus the toolbar is fully dockable. The programming interface is much the same as it was in earlier versions of the MFC library, however. The button images are easy to work with because a special resource type is supported by the resource editor. The old global buttons array is gone.

Assuming that AppWizard has generated the control bar code for your application, the user can enable and disable the toolbar and the status bar individually by choosing commands from the application's View menu. When a control bar is disabled, it disappears and the view size is recalculated. Apart from the common behavior just described, toolbar and status bar objects operate independently of each other and have rather different characteristics. In Visual C++ 6.0, a new MFC toolbar was introduced called the rebar. The rebar is based on the controls that come as part of Microsoft Internet Explorer 4.0 and provides a Microsoft Internet Explorer-style "sliding" toolbar. We will cover this later in this module.

 

The Toolbar

 

A toolbar consists of a number of horizontally (or vertically) arranged graphical buttons that might be clustered in groups. The programming interface determines the grouping. The graphical images for the buttons are stored in a single bitmap that is attached to the application's resource file. When a button is clicked, it sends a command message, as do menus and keyboard accelerators. An update command UI message handler is used to update the button's state, which in turn is used by the application framework to modify the button's graphical image.

 

The Toolbar Bitmap

 

Each button on a toolbar appears to have its own bitmap, but actually a single bitmap serves the entire toolbar. The toolbar bitmap has a tile, 15 pixels high and 16 pixels wide, for each button. The application framework supplies the button borders, and it modifies those borders, together with the button's bitmap tile color, to reflect the current button state. Figure 1 shows the relationship between the toolbar bitmap and the corresponding toolbar.

 

A toolbar bitmap and an actual toolbar.

 

Figure 1: A toolbar bitmap and an actual toolbar.

 

The toolbar bitmap is stored in the file Toolbar.bmp in the application's \res subdirectory. The bitmap is identified in the resource script (RC) file as IDR_MAINFRAME. You don't edit the toolbar bitmap directly; instead you use Visual C++'s special toolbar-editing facility.

 

Button States

 

Each button can assume the following states.

 

State

Meaning

0

Normal, un-pressed state.

TBSTATE_CHECKED

Checked (down) state.

TBSTATE_ENABLED

Available for use. Button is grayed and unavailable if this state is not set.

TBSTATE_HIDDEN

Not visible.

TBSTATE_INDETERMINATE

Grayed.

TBSTATE_PRESSED

Currently selected (pressed) with the mouse.

TBSTATE_WRAP

Line break follows the button.

 

Table 1.

A button can behave in either of two ways: it can be a pushbutton, which is down only when currently selected by the mouse, or it can be a check box button, which can be toggled up and down with mouse clicks. All buttons in the standard application framework toolbar are pushbuttons.

 

The Toolbar and Command Messages

 

When the user clicks a toolbar button with the mouse, a command message is generated. This message is routed like the menu command messages you saw in Module 7. Most of the time, a toolbar button matches a menu option. In the standard application framework toolbar, for example, the Disk button is equivalent to the File Save menu option because both generate the ID_FILE_SAVE command. The object receiving the command message doesn't need to know whether the message was produced by a click on the toolbar or by a selection from the menu.

A toolbar button doesn't have to mirror a menu item. If you don't provide the equivalent menu item, however, you are advised to define a keyboard accelerator for the button so that the user can activate the command with the keyboard or with a keyboard macro product for Microsoft Windows. You can use ClassWizard to define command and update command UI message handlers for toolbar buttons, whether or not they have corresponding menu items.

A toolbar has an associated bitmap resource and, in the RC file, a companion TOOLBAR resource that defines the menu commands associated with the buttons. Both the bitmap and the TOOLBAR resource have the same ID, typically IDR_MAINFRAME. The text of the AppWizard-generated TOOLBAR resource is shown below (you can open the RC file using text editor such as Notepad or WordPad):

 

IDR_MAINFRAME TOOLBAR DISCARDABLE  16, 15

BEGIN

    BUTTON      ID_FILE_NEW

    BUTTON      ID_FILE_OPEN

    BUTTON      ID_FILE_SAVE

        SEPARATOR

    BUTTON      ID_EDIT_CUT

    BUTTON      ID_EDIT_COPY

    BUTTON      ID_EDIT_PASTE

        SEPARATOR

    BUTTON      ID_FILE_PRINT

    BUTTON      ID_APP_ABOUT

END

 

The following is a portion of the RC file content for this Module program example.

 

Reource (RC) file content

 

Listing 1.

 

The SEPARATOR constants serve to group the buttons by inserting corresponding spaces on the toolbar. If the number of toolbar bitmap panes exceeds the number of resource elements (excluding separators), the extra buttons are not displayed. When you edit the toolbar with the resource editor, you're editing both the bitmap resource and the TOOLBAR resource. You select a button image, and then you double-click on the left panel to edit the properties, including the button's ID.

 

Toolbar Update Command UI Message Handlers

 

Remember from Module 7 that update command UI (User Interface) message handlers are used to disable or add check marks to menu items. These same message handlers apply to toolbar buttons. If your update command UI message handler calls the CCmdUI::Enable member function with a FALSE parameter, the corresponding button is set to the disabled (grayed) state and no longer responds to mouse clicks.

On a menu item, the CCmdUI::SetCheck member function displays a check mark. For the toolbar, the SetCheck() function implements check box buttons. If the update command UI message handler calls SetCheck() with a parameter value of 1, the button is toggled to the down (checked) state; if the parameter is 0, the button is toggled up (unchecked). If the SetCheck() parameter value is 2, the button is set to the indeterminate state. This state looks like the disabled state, but the button is still active and its color is a bit brighter.

The update command UI message handlers for a pop-up menu are called only when the menu is painted. The toolbar is displayed all the time, so when are its update command UI message handlers called? They're called during the application's idle processing, so the buttons can be updated continuously. If the same handler covers a menu item and a toolbar button, it is called both during idle processing and when the pop-up menu is displayed.

 

ToolTips

 

You've seen ToolTips in various Windows applications, including Visual C++. When the user positions the mouse on a toolbar button for a certain interval, text is displayed in a little ToolTip box next to the button as shown below.

 

ToolTips in action.

 

Figure 2: ToolTips in action.

 

In Module 7, you learned that menu items can have associated prompt strings, which are string resource elements with matching IDs as shown below.

 

Prompt string and ToolTips.

 

Figure 3: Prompt string and ToolTips.

 

To create a ToolTip, you simply add the tip text to the end of the menu prompt, preceded by a newline (\n) character as shown in Figure 3 (Toggle ToolBar). The resource editor lets you edit the prompt string while you are editing the toolbar images. Just double-click in the left panel.

 

Locating the Main Frame Window

 

The toolbar and status bar objects you'll be working with are attached to the application's main frame window, not to the view window. How does your view find its main frame window? In an SDI application, you can use the CWnd::GetParentFrame function. Unfortunately, this function won't work in an MDI application because the view's parent frame is the MDI child frame, not the MDI frame window.

If you want your view class to work in both SDI and MDI applications, you must find the main frame window through the application object. The AfxGetApp() global function returns a pointer to the application object. You can use that pointer to get the CWinApp data member m_pMainWnd. In an MDI application, AppWizard generates code that sets m_pMainWnd, but in an SDI application, the framework sets m_pMainWnd during the view creation process. Once m_pMainWnd is set, you can use it in a view class to get the frame's toolbar with statements such as this:

 

CMainFrame* pFrame = (CMainFrame*) AfxGetApp()->m_pMainWnd;

CToolBar* pToolBar = &pFrame->m_wndToolBar;

 

You'll need to cast m_pMainWnd from CFrameWnd* to CMainFrame* because m_wndToolBar is a member of that derived class. You'll also have to make m_wndToolBar public or make your class a friend of CMainFrame.

You can use similar logic to locate menu objects, status bar objects, and dialog objects. In an SDI application, the value of m_pMainWnd is not set when the view's OnCreate() message handler is called. If you need to access the main frame window in your OnCreate() function, you must use the GetParentFrame() function.

 

The MYMFC11 Toolbar Example

 

In this example, you will replace the standard application framework Edit, Cut, Copy, and Paste toolbar buttons with three special-purpose buttons that control drawing in the view window. You will also construct a Draw menu with three corresponding menu items, as follows.

 

Menu Item

Function

Circle

Draws a circle in the view window.

Square

Draws a square in the view window.

Pattern

Toggles a diagonal line fill pattern for new squares and circles.

 

Table 2.

 

The menu and toolbar options force the user to alternate between drawing circles and squares. After the user draws a circle, the Circle menu item and toolbar button are disabled; after the user draws a square, the Square menu item and toolbar button are disabled.

On the application's Draw menu, the Pattern menu item gets a check mark when pattern fill is active. On the toolbar, the corresponding button is a check box button that is down when pattern fill is active and up when it is not active. Figure 4 shows the application in action. The user has just drawn a square with pattern fill. Notice the states of the three drawing buttons.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

The MYMFC11 program in action.

 

Figure 4: The MYMFC11 program in action.

 

The MYMFC11 example introduces the resource editor for toolbars. You'll need to do very little C++ coding. Simply follow these steps:

 

Run AppWizard to generate \mfcproject\mymfc11 (or wherever you have designated the project folder). 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.

 

MYMFC11 project summary.

 

Figure 5: MYMFC11 project summary.

 

Use the resource editor to edit the application's main menu. In ResourceView, double-click on IDR_MAINFRAME under Menu. Edit the IDR_MAINFRAME menu resource to create a menu that looks like this which means you'll need to change the Edit menu.

 

Adding and modifying new menus properties.

 

Figure 6: Adding and modifying new menus properties.

 

Use the following command IDs for your new menu items.

 

Menu

Caption

Command ID

Draw

Circle

ID_DRAW_CIRCLE

Draw

Square

ID_DRAW_SQUARE

Draw

Pattern

ID_DRAW_PATTERN

 

Table 3

 

When you're in the Menu Item Properties dialog, add some appropriate prompt strings and ToolTips (following a newline character). The string for ID_DRAW_CIRCLE might be "Draw a circle\nCircle."

 

Bitmap Image example

 

Use the resource editor to update the application's toolbar. Edit the IDR_MAINFRAME toolbar resource to create a bitmap that looks like the following. Start with by clicking the last grey button.

 

Creating a bitmap for our new toolbar item.

 

Figure 7: Creating a bitmap for our new toolbar item.

 

You'll be erasing the Edit Cut, Copy, and Paste tiles (fourth, fifth, and sixth from the left) and replacing them with new tiles. The toolbar editor is fairly intuitive. You simply move the buttons around with the mouse. The Delete key erases a button's pixels. If you want to eliminate a button entirely, just drag it off the toolbar. Use the rectangle and ellipse tools from the graphics toolbar. Experiment with different line widths. Save the resource file when you're done, just in case.

 

Using toolbar editor to create new toolbar bitmap.

 

Figure 8: Using toolbar editor to create new toolbar bitmap.

 

 

Double click the button and assign the IDs ID_DRAW_CIRCLE, ID_DRAW_SQUARE, and ID_DRAW_PATTERN to the three new buttons.

 

Creating and modifying new toolbar bitmap properties.

 

Figure 9: Creating and modifying new toolbar bitmap properties.

 

Use ClassWizard to add CMymfc11View view class message handlers. Add message handlers for the following command and update command UI messages, and accept the default function names shown in the following table.

 

Object ID

Message

Member Function

ID_DRAW_CIRCLE

COMMAND

OnDrawCircle()

ID_DRAW_CIRCLE

UPDATE_COMMAND_UI

OnUpdateDrawCircle()

ID_DRAW_PATTERN

COMMAND

OnDrawPattern()

ID_DRAW_PATTERN

UPDATE_COMMAND_UI

OnUpdateDrawPattern()

ID_DRAW_SQUARE

COMMAND

OnDrawSquare()

ID_DRAW_SQUARE

UPDATE_COMMAND_UI

OnUpdateDrawSquare()

 

Table 4

 

Adding CMymfc11View view class message handlers.

 

Figure 10: Adding CMymfc11View view class message handlers.

 

Add three data members to the CMymfc11View class. Edit the file mymfc11View.h, or use ClassView.

 

private:

    CRect m_rect;

    BOOL  m_bCircle;

    BOOL  m_bPattern;

 

Adding data members/variable to the CMymfc11View class.

 

Figure 11: Adding data members/variable to the CMymfc11View class.

 

Edit the mymfc11View.cpp file. The CMymfc11View constructor simply initializes the class data members. Add the following code:

 

CMymfc11View::CMymfc11View() : m_rect(0, 0, 100, 100)

{

    m_bCircle = TRUE;

    m_bPattern = FALSE;

}

 

Visual C++ code segment

 

Listing 2.

 

The OnDraw() function draws an ellipse or a rectangle, depending on the value of the m_bCircle flag. The brush is plain white or a diagonal pattern, depending on the value of m_bPattern.

 

void CMymfc11View::OnDraw(CDC* pDC)

{

    // brush with diagonal pattern

    CBrush brush(HS_BDIAGONAL, 0L);

 

    if (m_bPattern)

    {

        pDC->SelectObject(&brush);

    }

    else

    {

        pDC->SelectStockObject(WHITE_BRUSH);

    }

    if (m_bCircle)

    {

        pDC->Ellipse(m_rect);

    }

    else {

        pDC->Rectangle(m_rect);

    }

    // Deselects brush if selected

    pDC->SelectStockObject(WHITE_BRUSH);

}

 

Visual C++ code segment

Listing 3.

 

The OnDrawCircle() function handles the ID_DRAW_CIRCLE command message, and the OnDrawSquare() function handles the ID_DRAW_SQUARE command message. These two functions move the drawing rectangle down and to the right, and then they invalidate the rectangle, causing the OnDraw() function to redraw it. The effect of this invalidation strategy is a diagonal cascading of alternating squares and circles. Also, the display is not buffered, so when the window is hidden or minimized, previously drawn items are not redisplayed.

 

void CMymfc11View::OnDrawCircle()

{

    m_bCircle = TRUE;

    m_rect += CPoint(25, 25);

    InvalidateRect(m_rect);

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

Visual C++ code segment

Listing 4.

 

 

 

void CMymfc11View::OnDrawSquare()

{

    m_bCircle = FALSE;

    m_rect += CPoint(25, 25);

    InvalidateRect(m_rect);

}

 

Visual C++ code segment

 

Listing 5.

 

The following two update command UI functions alternately enable and disable the Circle and Square buttons and corresponding menu items. Only one item can be enabled at a time.

 

void CMymfc11View::OnUpdateDrawCircle(CCmdUI* pCmdUI)

{

    pCmdUI->Enable(!m_bCircle);

}

 

Visual C++ code segment

 

Listing 6.

 

void CMymfc11View::OnUpdateDrawSquare(CCmdUI* pCmdUI)

{

    pCmdUI->Enable(m_bCircle);

}

 

Visual C++ code segment

 

Listing 7.

 

The OnDrawPattern() function toggles the state of the m_bPattern flag.

 

void CMymfc11View::OnDrawPattern()

{

    m_bPattern ^= 1;

}

 

Visual C++ code segment

 

Listing 8.

 

The OnUpdateDrawPattern() function updates the Pattern button and menu item according to the state of the m_bPattern flag. The toolbar button appears to move in and out, and the menu item check mark appears and disappears.

 

void CMymfc11View::OnUpdateDrawPattern(CCmdUI* pCmdUI)

{

    pCmdUI->SetCheck(m_bPattern);

}

 

Visual C++ code segment

 

Listing 9.

 

Build and test the MYMFC11 application.

 

MYMFC11 program output with new toolbar buttons.

 

Figure 12: MYMFC11 program output with new toolbar buttons.

 

Notice the behavior of the toolbar buttons. Try the corresponding menu items, and notice that they too are enabled, disabled, and checked as the application's state changes. Observe the ToolTip when you stop the mouse pointer on one of the new toolbar buttons.

 

MYMFC11 program output in action.

 

Figure 13: MYMFC11 program output in action.

 

 

Continue on next module...part 2.

 

 

 

 

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 C & C++ | MFC Home | Menus, Key Acc., Rich Edit & Property Sheets 4 | Toolbars, Status Bars and ReBar 2 | Download | Site Index |