The EX14A 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 ItemFunction
CircleDraws a circle in the view window
SquareDraws a square in the view window
PatternToggles a diagonal line fill pattern for new squares and circles

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 14-2 shows the application in action. The user has just drawn a square with pattern fill. Notice the states of the three drawing buttons.

Click to view at full size.

Figure 14-2. The EX14A program in action.

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

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

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

    Use the following command IDs for your new menu items.

    MenuCaptionCommand ID
    Draw CircleID_DRAW_CIRCLE
    Draw SquareID_DRAW_SQUARE
    Draw PatternID_DRAW_PATTERN

    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."

  1. Use the resource editor to update the application's toolbar. Edit the IDR_MAINFRAME toolbar resource to create a bitmap that looks like this.

    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.

    Assign the IDs ID_DRAW_CIRCLE, ID_DRAW_SQUARE, and ID_DRAW_PATTERN to the three new buttons.

  1. Use ClassWizard to add CEx14aView 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 IDMessageMember Function
    ID_DRAW_CIRCLECOMMANDOnDrawCircle
    ID_DRAW_CIRCLEUPDATE_COMMAND_UI OnUpdateDrawCircle
    ID_DRAW_PATTERNCOMMANDOnDrawPattern
    ID_DRAW_PATTERNUPDATE_COMMAND_UI OnUpdateDrawPattern
    ID_DRAW_SQUARECOMMANDOnDrawSquare
    ID_DRAW_SQUAREUPDATE_COMMAND_UI OnUpdateDrawSquare

  1. Add three data members to the CEx14aView class. Edit the file ex14aView.h, or use ClassView.

    private:
        CRect m_rect;
        BOOL  m_bCircle;
        BOOL  m_bPattern;
    

  2. Edit the ex14aView.cpp file. The CEx14aView constructor simply initializes the class data members. Add the following boldface code:

    CEx14aView::CEx14aView() : m_rect(0, 0, 100, 100)
    {
        m_bCircle = TRUE;
        m_bPattern = FALSE;
    }
    

    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 CEx14aView::OnDraw(CDC* pDC)
    {
        CBrush brush(HS_BDIAGONAL, 0L); // brush with diagonal pattern
    
        if (m_bPattern) {
            pDC->SelectObject(&brush);
        }
        else {
            pDC->SelectStockObject(WHITE_BRUSH);
        }
        if (m_bCircle) {
            pDC->Ellipse(m_rect);
        }
        else {
            pDC->Rectangle(m_rect);
        }
        pDC->SelectStockObject(WHITE_BRUSH); // Deselects brush
                                             //  if selected
    }
    

    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 CEx14aView::OnDrawCircle()
    {
        m_bCircle = TRUE;
        m_rect += CPoint(25, 25);
        InvalidateRect(m_rect);
    }
    
    void CEx14aView::OnDrawSquare()
    {
        m_bCircle = FALSE;
        m_rect += CPoint(25, 25);
        InvalidateRect(m_rect);
    }
    

    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 CEx14aView::OnUpdateDrawCircle(CCmdUI* pCmdUI)
    {
        pCmdUI->Enable(!m_bCircle);
    }
    
    void CEx14aView::OnUpdateDrawSquare(CCmdUI* pCmdUI)
    {
        pCmdUI->Enable(m_bCircle);
    }
    

    The OnDrawPattern function toggles the state of the m_bPattern flag.

    void CEx14aView::OnDrawPattern()
    {
        m_bPattern ^= 1;
    }

    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 CEx14aView::OnUpdateDrawPattern(CCmdUI* pCmdUI)
    {
        pCmdUI->SetCheck(m_bPattern);
    }
    

  3. Build and test the EX14A application. 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.