ÄúµÄλÖãºÑ°ÃÎÍøÊ×Ò³£¾±à³ÌÀÖÔ°£¾C/C++±à³Ì£¾Teach Yourself Visual C++ 6 in 21 Days


Teach Yourself Visual C++ 6 in 21 Days

Previous chapterNext chapterContents


- 12 -
Adding Toolbars and Status Bars



When you created your SDI and MDI applications, they not only came with default menus already attached, but also they came with simple toolbars to go with the menus. These simple toolbars had the standard set of functions (New, Open, Save, Print, Cut, Copy, and Paste) that are on the toolbars of most Windows applications. Most applications don't limit their toolbars to just this standard selection of functions but have customized toolbars that reflect the specific functionality of the application.

In addition to the toolbars, the SDI and MDI applications have a status bar at the bottom of the frame that provides textual descriptions of the toolbar buttons and menu entries. The status bar also has default areas that display whether the Caps, Num, and Scroll Lock keys are on.

Today, you will learn

  • How to design your own toolbar.

  • How to attach your toolbar to the application frame.

  • How to show and hide your toolbar with a menu entry.

  • How to place a combo box on your toolbar.

  • How to display descriptions of your toolbar entries in the status bar.

  • How to add your own status bar elements.

Toolbars, Status Bars, and Menus

One of the driving intentions behind the development of Graphical User Interfaces (GUI) such as Windows was the goal of making computers easier to use and learn. In the effort to accomplish this goal, GUI designers stated that all applications should use a standard set of menus and that the menus should be organized in a standardized manner. When Microsoft designed the Windows operating system, it followed this same philosophy, using a standard set of menus organized in a standard order on most of its applications.

A funny thing happened once Windows became widely used. The application designers found that new users still had a difficult time learning new applications and that advanced users found the menus cumbersome. As a result, the application designers invented toolbars as one solution to both problems.

A toolbar is a small band attached to the window frame or a dialog window that is floating independent of the application frame. This band (or dialog) has a number of small buttons containing graphic images that can be used in place of the menus. The application designers place the most commonly used functions for their applications on these toolbars and do their best to design graphical images that illustrate the functions the buttons serve.

Once advanced users learned what each of the toolbar buttons do, the toolbars were a hit. However, novice users still had problems learning what the toolbar does. As a result, the application designers went back to the drawing board to come up with ways to help the new user learn how use the toolbar buttons.

One of the solutions was to use the information bar that many of them had begun placing at the bottom of application windows to provide detailed descriptions of both menu entries and toolbar buttons. One of the other solutions was to provide a little pop-up window with a short description of the button that appears whenever the mouse is positioned over the button for more than a couple of seconds. The first of these solutions became known as the status bar, and the second became known as tooltips. Both solutions are in common practice with most Windows applications today.

If you want to design and use your own toolbars and status bars in your applications, you might think that Visual C++ provides plenty of support for your efforts and even makes it easy to implement. After all, Microsoft's own application developers have been in the forefront of developing these elements, and most, if not all, of Microsoft's Windows applications are developed using its own Visual C++. Well, you are correct in making that assumption, and today, you'll learn how to create your own custom toolbars and status bars for your applications.

Designing a Toolbar

For learning how to create your own toolbar, you will modify the application that you created on Day 10, "Creating Single Document Interface Applications," the SDI drawing application, to add a toolbar for selecting the color to use in drawing.


NOTE: Although the sample application you are working with today is an extension to the application you built on Day 10, all file and class names have been changed from Day10 to Toolbar. If you are making the changes in the Day 10 project, then when the following text specifies that you make changes to the CToolbarDoc class, you should make the changes to the CDay10Doc class. Likewise, when you are asked to edit the Toolbar.rc file, you can edit the Day10.rc file.

If all you want to do is add a few additional toolbar buttons to the default toolbar that the AppWizard creates when you start a new SDI or MDI application, you can pull up the toolbar in the Visual C++ designer through the Resource View in the workspace pane and begin adding new buttons. Just as in the Menu Designer, the end of the toolbar always has a blank entry, waiting for you to turn it into another toolbar button, as shown in Figure 12.1. All you have to do is select this blank button, drag it to the right if you want a separator between it and the button beside it, or drag it to a different position if you want it moved. After you have the button in the desired location, you paint an icon on the button that illustrates the function that the button will trigger. Finally, double-click the button in the toolbar view to open the button's properties dialog and give the button the same ID as the menu that it will trigger. The moment that you compile and run your application, you will have a new toolbar button that performs a menu selection that you chose. If you want to get rid of a toolbar button, just grab it on the toolbar view, and drag it off the toolbar.

FIGURE 12.1. The toolbar designer.

Creating a New Toolbar

To insert a new toolbar, right-click on the Toolbar folder and select Insert Toolbar from the pop-up menu. This creates an empty toolbar with a single blank button. As you start drawing an icon on each of the blank buttons in the toolbar, another blank button is added on the end.

For use in your drawing application, fill eight buttons with the eight colors available in the drawing application.

Once you draw icons on each of the buttons in your toolbar, double-click on the first button in the toolbar view. This should open the toolbar button properties dialog. In the ID field, enter (or select from the drop-down list) the ID of the menu that this toolbar button should trigger. In the Prompt field, enter the description that should appear in the status bar for this toolbar button. (If you entered a prompt for the menu, then this field is automatically populated with the menu description.) At the end of the status bar description, add \n and a short description to appear in the tooltips for the toolbar button.


NOTE: In C/C++, the \n string is a shorthand notation for "begin a new line." In the prompt for toolbar buttons and menu entries, this string is used to separate the status bar descriptions of the menu entries and the tooltips pop-up prompt that appears when the mouse is held over a toolbar button for a few seconds. The first line of the prompt is used for the status bar description, and the second line is used for the tooltips description. The tooltips description is only used with the toolbars, so there's no reason to add this for menu entries that will have no toolbar equivalents.

For example, for the black button on the toolbar that you are creating for your drawing application, enter an ID of ID_COLOR_BLACK and a prompt of Black drawing color\nBlack, as shown in Figure 12.2.

FIGURE 12.2. The toolbar button properties dialog.

Once you finish designing your toolbar and have icons on all of your buttons with the properties set for each button, you will change the toolbar ID. In the workspace pane, right-click the new toolbar that you just added and open its properties dialog. Change the toolbar ID to a descriptive name.

As an example, for the color toolbar that you created for your drawing application, change the toolbar ID to IDR_TBCOLOR.

Attaching the Toolbar to the Application Frame

In the previous SDI and MDI applications, you didn't add any functionality that required you to touch the frame window. Well, because the toolbar is attached to the frame, you'll have to begin adding and modifying code in that module. If you open the CMainFrame class to the OnCreate function, you'll see where it's creating the existing toolbar and then later in this function where the toolbar is being attached to the frame.

Before you can add your toolbar to the application frame, you need to add a variable to the CMainFrame class to hold the new toolbar. This variable of type CToolBar should be protected in accessibility.

To add your color toolbar to your draw application, right-click the CMainFrame class in the Class View tab of the workspace pane. Select Add Member Variable from the pop-up menu, and specify the variable type as CToolBar, the name as m_wndColorBar, and the access as protected.

After you add a variable for your toolbar, you need to add some code in the OnCreate function in the CMainFrame class to add the toolbar and attach it to the frame. Make the modifications in Listing 12.1 to add the color toolbar to your drawing application.

LISTING 12.1. THE MODIFIED CMainFrame.OnCreate FUNCTION.

 1:  int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
 2: {
 3:     if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
 4:         return -1;
 5:
 6:     if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT,
                  ÂWS_CHILD | WS_VISIBLE | CBRS_TOP
 7:         | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY |         ÂCBRS_SIZE_DYNAMIC) ||
 8:         !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
 9:     {
10:         TRACE0("Failed to create toolbar\n");
11:         return -1;      // fail to create
12:     }
13:
14:     ///////////////////////
15:     // MY CODE STARTS HERE
16:     ///////////////////////
17:
18:     // Add the color toolbar
19:     int iTBCtlID;
20:     int i;
21:
22:     // Create the Color Toolbar
23:     if (!m_wndColorBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD |
24:         WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS |
25:         CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
26:         !m_wndColorBar.LoadToolBar(IDR_TBCOLOR))
27:     {
28:         TRACE0("Failed to create toolbar\n");
29:         return -1;      // fail to create
30:     }
31:     // Find the Black button on the toolbar
32:     iTBCtlID = m_wndColorBar.CommandToIndex(ID_COLOR_BLACK);
33:     if (iTBCtlID >= 0)
34:     {
35:         // Loop through the buttons, setting them to act as radio                 Âbuttons
36:         for (i= iTBCtlID; i < (iTBCtlID + 8); i++)
37:             m_wndColorBar.SetButtonStyle(i, TBBS_CHECKGROUP);
38:     }
39:
40:     ///////////////////////
41:     // MY CODE ENDS HERE
42:     ///////////////////////
43:
44:     if (!m_wndStatusBar.Create(this) ||
45:         !m_wndStatusBar.SetIndicators(indicators,
46:           sizeof(indicators)/sizeof(UINT)))
47:     {
48:         TRACE0("Failed to create status bar\n");
49:         return -1;      // fail to create
50:     }
51:
52:     // TODO: Delete these three lines if you don't want the toolbar to
53:     //  be dockable
54:     m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
55:
56:     ///////////////////////
57:     // MY CODE STARTS HERE
58:     ///////////////////////
59:
60:     // Enable docking for the Color Toolbar
61:     m_wndColorBar.EnableDocking(CBRS_ALIGN_ANY);
62:
63:     ///////////////////////
64:     // MY CODE ENDS HERE
65:     ///////////////////////
66:
67:     EnableDocking(CBRS_ALIGN_ANY);
68:     DockControlBar(&m_wndToolBar);
69:
70:     ///////////////////////
71:     // MY CODE STARTS HERE
72:     ///////////////////////
73:
74:     // Dock the Color Toolbar
75:     DockControlBar(&m_wndColorBar);
76:
77:     ///////////////////////
78:     // MY CODE ENDS HERE
79:     ///////////////////////
80:
81:     return 0;
82: }

Creating the Toolbar

The first part of the code you added,

if (!m_wndColorBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD |
    WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS |
    CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
    !m_wndColorBar.LoadToolBar(IDR_TBCOLOR))

contains two separate functions that are necessary in creating a toolbar. The first function, CreateEx, creates the toolbar itself, whereas the second, LoadToolBar, loads the toolbar that you designed in the toolbar designer. The second function, LoadToolBar, requires a single argument, the ID for the toolbar that you want to create.

The CreateEx function has several arguments that you can pass with the function. The first argument, and the only required argument, is a pointer to the parent window. In this case (which is normally the case), this argument is a pointer to the frame window to which the toolbar will be attached.

The second argument is the style of controls on the toolbar that is to be created. Several toolbar control styles are available for use, some of which have been introduced with the last two versions of Internet Explorer. Table 12.1 lists the available styles.

TABLE 12.1. TOOLBAR CONTROL STYLES.

Style Description
TBSTYLE_ALTDRAG Allows the user to move the toolbar by dragging it while holding down the Alt key.
TBSTYLE_CUSTOMERASE Generates a NM_CUSTOMDRAW message when erasing the toolbar and button background, allowing the programmer to choose when and whether to control the background erasing process.
TBSTYLE_FLAT Creates a flat toolbar. Button text appears under the bitmap image.
TBSTYLE_LIST Button text appears to the right of the bitmap image.
TBSTYLE_REGISTERDROP For use in dragging and dropping objects onto toolbar buttons.
TBSTYLE_TOOLTIPS Creates a tooltip control that can be used to display descriptive text for the buttons.
TBSTYLE_TRANSPARENT Creates a transparent toolbar.
TBSTYLE_WRAPABLE Creates a toolbar that can have multiple rows of buttons.

The third argument is the style of the toolbar itself. This argument is normally a combination of window and control bar styles. Normally, only two or three window styles are used, and the rest of the toolbar styles are control bar styles. The list of the normally used toolbar styles appears in Table 12.2.

TABLE 12.2. TOOLBAR STYLES.

Style Description
WS_CHILD The toolbar is created as a child window.
WS_VISIBLE The toolbar will be visible when created.
CBRS_ALIGN_TOP Allows the toolbar to be docked to the top of the view area of the frame window.
CBRS_ALIGN_BOTTOM Allows the toolbar to be docked to the bottom of the view area of the frame window.
CBRS_ALIGN_LEFT Allows the toolbar to be docked to the left side of the view area of the frame window.
CBRS_ALIGN_RIGHT Allows the toolbar to be docked to the right side of the view area of the frame window.
CBRS_ALIGN_ANY Allows the toolbar to be docked to any side of the view area of the frame window.
CBRS_BORDER_TOP Places a border on the top edge of the toolbar when the top of the toolbar is not docked.
CBRS_BORDER_BOTTOM Places a border on the bottom edge of the toolbar when the top of the toolbar is not docked.
CBRS_BORDER_LEFT Places a border on the left edge of the toolbar when the top of the toolbar is not docked.
CBRS_BORDER_RIGHT Places a border on the right edge of the toolbar when the top of the toolbar is not docked.
CBRS_FLOAT_MULTI Allows multiple toolbars to be floated in a single miniframe window.
CBRS_TOOLTIPS Causes tooltips to be displayed for the toolbar buttons.
CBRS_FLYBY Causes status bar message text to be updated for the toolbar buttons at the same time as the tooltips.
CBRS_GRIPPER Causes a gripper to be drawn on the toolbar.

The fourth argument, which you did not provide in your code, is the size of the toolbar borders. This argument is passed as a standard CRect rectangle class to provide the length and height desired for the toolbar. The default value is 0 for all of the rectangle dimensions, thus resulting in a toolbar with no borders.

The fifth and final argument, which you also did not provide in your code, is the toolbar's child window ID. This defaults to AFX_IDW_TOOLBAR, but you can specify any defined ID that you need or want to use for the toolbar.

Setting the Button Styles

After you create the toolbar, there is a curious bit of code:

// Find the Black button on the toolbar
iTBCtlID = m_wndColorBar.CommandToIndex(ID_COLOR_BLACK);
if (iTBCtlID >= 0)
{
    // Loop through the buttons, setting them to act as radio buttons
    for (i= iTBCtlID; i < (iTBCtlID + 8); i++)
        m_wndColorBar.SetButtonStyle(i, TBBS_CHECKGROUP);
}

The first line in this code snippet uses the CommandToIndex toolbar function to locate the control number of the ID_COLOR_BLACK button. If you design your toolbar in the order of colors that you used on the menu, this should be the first control, with a index of 0. It's best to use the CommandToIndex function to locate the index of any toolbar button that you need to alter, just in case it's not where you expect it to be. This function returns the index of the toolbar control specified, and you use this as a starting point to specify the button style of each of the color buttons.

In the loop, where you are looping through each of the eight color buttons on the toolbar, you use the SetButtonStyle function to control the behavior of the toolbar buttons. The first argument to this function is the index of the button that you are changing. The second argument is the style of button that you want for the toolbar button specified. In this case, you are specifying that each of the buttons be TBBS_CHECKGROUP buttons, which makes them behave like radio buttons, where only one of the buttons in the group can be selected at any time. The list of the available button styles is in Table 12.3.

TABLE 12.3. TOOLBAR BUTTON STYLES.

Style Description
TBSTYLE_AUTOSIZE The button's width will be calculated based on the text on the button.
TBSTYLE_BUTTON Creates a standard push button.
TBSTYLE_CHECK Creates a button that acts like a check box, toggling between the pressed and unpressed state.
TBSTYLE_CHECKGROUP Creates a button that acts like a radio button, remaining in the pressed state until another button in the group is pressed. This is actually the combination of the TBSTYLE_CHECK and TBSTYLE_GROUP button styles.
TBSTYLE_DROPDOWN Creates a drop-down list button.
TBSTYLE_GROUP Creates a button that remains pressed until another button in the group is pressed.
TBSTYLE_NOPREFIX The button text will not have an accelerator prefix associated with it.
TBSTYLE_SEP Creates a separator, making a small gap between the buttons on either side.

Docking the Toolbar

The last thing that you do in the code that you add to the OnCreate function in the CMainFrame class is the following:

// Enable docking for the Color Toolbar
m_wndColorBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);  // (AppWizard generated line)
// Dock the Color Toolbar
DockControlBar(&m_wndColorBar);

In the first of these lines, you called the EnableDocking toolbar function. This function enables the toolbar for docking with the frame window. The value passed to this toolbar function must match the value passed in the following EnableDocking function that is called for the frame window. The available values for these functions are listed in Table 12.4. These functions enable the borders of the toolbar, and the frame window, for docking. If these functions are not called, then you will not be able to dock the toolbar with the frame window. If a specific side is specified in these functions for use in docking, and the sides do not match, you will not be able to dock the toolbar with the frame.

TABLE 12.4. TOOLBAR DOCKING SIDES.

Style Description
CBRS_ALIGN_TOP Allows the toolbar to be docked to the top of the view area of the frame window.
CBRS_ALIGN_BOTTOM Allows the toolbar to be docked to the bottom of the view area of the frame window.
CBRS_ALIGN_LEFT Allows the toolbar to be docked to the left side of the view area of the frame window.
CBRS_ALIGN_RIGHT Allows the toolbar to be docked to the right side of the view area of the frame window.
CBRS_ALIGN_ANY Allows the toolbar to be docked to any side of the view area of the frame window.
CBRS_FLOAT_MULTI Allows multiple toolbars to be floated in a single miniframe window.
0 The toolbar will not be able to dock with the frame.

The final function that you added was a frame window function, DockControlBar, which is passed the address of the toolbar variable. This function physically docks the toolbar to the frame window. Because all of this code appears in the OnCreate function for the frame window, the toolbar is docked before the user sees either the window or the toolbar.

Now, after adding all of this code to the OnCreate function of the CMainFrame class, if you compile and run your application, you'll find a working color toolbar that you can use to select the drawing color, as shown in Figure 12.3.

FIGURE 12.3. The color toolbar on the drawing program.

Controlling the Toolbar Visibility

Now that you have your color toolbar on the frame of your drawing application, it would be nice to be able to show and hide it just as you can the default toolbar and status bar through the View menu. This is simple enough functionality to add, but it doesn't necessarily work the way you might expect it to.

The first thing you need to do is add a menu entry to toggle the visibility of the color bar. Do this through the Menu Designer, adding a new menu entry on the View menu. Specify the menu properties as shown in Table 12.5.

TABLE 12.5. COLOR BAR MENU PROPERTIES.

Property Setting
ID ID_VIEW_COLORBAR
Caption &Color Bar
Prompt Show or hide the colorbar\nToggle ColorBar

Updating the Menu

To determine whether the toolbar is visible or hidden, you can get the current style of the toolbar and mask out for the WS_VISIBLE style flag. If the flag is in the current toolbar style, then the toolbar is visible. By placing this evaluation into the SetCheck function in the UPDATE_COMMAND_UI event message handler, you can check and uncheck the color bar menu entry as needed.

To add this functionality to your drawing program, add an event handler for the UPDATE_COMMAND_UI event message on the ID_VIEW_COLOR menu. Be sure to add this event-handler function into the CMainFrame class. (You're still making all of your coding changes so far in the frame class.) Edit the event-handler function, adding the code in Listing 12.2.

LISTING 12.2. THE MODIFIED CMainFrame.OnUpdateViewColorbar FUNCTION.

 1: void CMainFrame::OnUpdateViewColorbar(CCmdUI* pCmdUI)
 2: {
 3:     // TODO: Add your command update UI handler code here
 4:     ///////////////////////
 5:     // MY CODE STARTS HERE
 6:     ///////////////////////
 7:
 8:     // Check the state of the color toolbar
 9:     pCmdUI->SetCheck(((m_wndColorBar.GetStyle() & WS_VISIBLE) != 0));
10:
11:     ///////////////////////
12:     // MY CODE ENDS HERE
13:     ///////////////////////
14: }

Toggling the Toolbar Visibility

Because the CToolBar class is derived from the CWnd class (via the CControlBar class), you might think that you could call the ShowWindow function on the toolbar itself to show and hide the toolbar. Well, you can, but the background for the toolbar will not be hidden along with the toolbar. All the user would notice is the toolbar buttons appearing and disappearing. (Of course, this might be the effect you are after, but your users might not like it.)

Instead, you use a frame window function, ShowControlBar, to show and hide the toolbar. This function takes three arguments. The first argument is the address for the toolbar variable. The second argument is a boolean, specifying whether to show the toolbar. (TRUE shows the toolbar; FALSE hides the toolbar.) Finally, the third argument specifies whether to delay showing the toolbar. (TRUE delays showing the toolbar; FALSE shows the toolbar immediately.)

Once a toolbar is toggled on or off, you need to call another frame window function, RecalcLayout. This function causes the frame to reposition all of the toolbars, status bars, and anything else that is within the frame area. This is the function that causes the color toolbar to move up and down if you toggle the default toolbar on and off.

To add this functionality to your drawing program, add an event handler for the COMMAND event message on the ID_VIEW_COLOR menu. Be sure to add this event-handler function into the CMainFrame class. (You're still making all of your coding changes so far in the frame class.) Edit the event-handler function, adding the code in Listing 12.3.

LISTING 12.3. THE MODIFIED CMainFrame.OnViewColorbar FUNCTION.

 1: void CMainFrame::OnViewColorbar()
 2: {
 3:     // TODO: Add your command handler code here
 4:
 5:     ///////////////////////
 6:     // MY CODE STARTS HERE
 7:     ///////////////////////
 8:     BOOL bVisible;
 9:
10:     // Check the state of the color toolbar
11:     bVisible = ((m_wndColorBar.GetStyle() & WS_VISIBLE) != 0);
12:
13:     // Toggle the color bar
14:     ShowControlBar(&m_wndColorBar, !bVisible, FALSE);
15:     // Reshuffle the frame layout
16:     RecalcLayout();
17:
18:     ///////////////////////
19:     // MY CODE ENDS HERE
20:     ///////////////////////
21: }

At this point, after compiling and running your application, you should be able to toggle your color toolbar on and off using the View menu.

Adding a Combo Box to a Toolbar

It's commonplace now to use applications that have more than just buttons on toolbars. Look at the Visual C++ Developer Studio, for example. You've got combo boxes that enable you to navigate through your code by selecting the class, ID, and function to edit right on the toolbar. So how do you add a combo box to a toolbar? It's not available in the toolbar designer; all you have there are buttons that you can paint icons on. You can't add a combo box to any toolbar by using any of the Visual C++ wizards. You have to write a little C++ code to do it.

To learn how to add a combo box to a toolbar, you'll add a combo box to the color toolbar you just created. The combo box will be used to select the width of the pen the user will use to draw images. (If you haven't added the support for different drawing widths from the exercise at the end of Day 10, you might want to go back and add that now.)

Editing the Project Resources

To add a combo box to your toolbar, the first thing that you need to do is what Visual C++ was designed to prevent you from having to do. You need to edit the resource file yourself. You cannot do this through the Visual C++ Developer Studio. If you try to open the resource file in the Developer Studio, you will be popped into the Resource View tab of the workspace pane, editing the resource file through the various resource editors and designers. No, you'll have to edit this file in another editor, such as Notepad.

Close Visual C++, the only way to guarantee that you don't write over your changes. Open Notepad and navigate to your project directory. Open the resource file, which is named after the project with a .rc filename extension. Once you open this file in Notepad, scroll down until you find the toolbar definitions. (You can search for the word "toolbar.") Once you've found the toolbar definitions, go to the end of the Color toolbar definition and add two separator lines at the bottom of the toolbar definition.

For instance, to make these changes to your drawing application, you need to navigate to the Toolbar project directory and then open the Toolbar.rc file. (If you are adding these toolbars to the MDI drawing application, you need to look for the Day11.rc file.) Search for the toolbar section, and then add two SEPARATOR lines just before the end of the IDR_TBCOLOR section, as shown in Listing 12.4. Once you add these two lines, save the file, exit Notepad, and restart Visual C++, reloading the project.

LISTING 12.4. THE MODIFIED PROJECT RESOURCE FILE (Toolbar.rc).

 1: //////////////////////////////////////////////////////////////////////
 2: //
 3: // Toolbar
 4: //
 5:
 6: IDR_MAINFRAME TOOLBAR DISCARDABLE  16, 15
 7: BEGIN
 8:     BUTTON      ID_FILE_NEW
 9:     BUTTON      ID_FILE_OPEN
10:     BUTTON      ID_FILE_SAVE
11:     SEPARATOR
12:     BUTTON      ID_EDIT_CUT
13:     BUTTON      ID_EDIT_COPY
14:     BUTTON      ID_EDIT_PASTE
15:     SEPARATOR
16:     BUTTON      ID_FILE_PRINT
17:     BUTTON      ID_APP_ABOUT
18: END
19:
20: IDR_TBCOLOR TOOLBAR DISCARDABLE  16, 15
21: BEGIN
22:     BUTTON      ID_COLOR_BLACK
23:     BUTTON      ID_COLOR_BLUE
24:     BUTTON      ID_COLOR_GREEN
25:     BUTTON      ID_COLOR_CYAN
26:     BUTTON      ID_COLOR_RED
27:     BUTTON      ID_COLOR_MAGENTA
28:     BUTTON      ID_COLOR_YELLOW
29:     BUTTON      ID_COLOR_WHITE
30:     SEPARATOR
31:     SEPARATOR
32: END

You added these two SEPARATOR lines in the toolbar definition so that the second separator can act as a place holder for the combo box that you are going to add to the toolbar. There are two reasons that you had to make this edit by hand and not use the Visual C++ toolbar designer. The first reason is that the toolbar designer would not allow you to add more than one separator to the end of the toolbar. The second reason is that, if you don't add anything else on the end of your toolbar after the separator, the toolbar designer decides that the separator is a mistake and removes it for you. In other words, the Visual C++ toolbar designer does not allow you to add the place holder for the combo box to your toolbar.

Next, you need to add the text strings that you will load into your combo box. To add these strings, you need to open the string table in the Resource View of the workspace pane. Here you find all of the strings that you entered as prompts in various properties dialogs. This table has a number of IDs, the values of those IDs, and textual strings that are associated with those IDs, as shown in Figure 12.4. You'll need to add the strings to be placed into your toolbar combo box in the string table; each line in the drop-down list must have a unique ID and entry in the strings table.

FIGURE 12.4. The string table editor.

For instance, to add the strings for the combo box that you will be adding to the color toolbar, insert a new string, either by selecting Insert|New String from the menu or by right-clicking the string table and selecting New String from the pop-up menu.

In the String properties dialog, specify a string ID for the string and then enter the string to appear in the drop-down list. Close the properties dialog to add the string. For the strings in the Width combo box that you are going to add to the color toolbar, add the strings in Table 12.6.

TABLE 12.6. WIDTH TOOLBAR COMBO BOX STRINGS.

ID Caption
IDS_WIDTH_VTHIN Very Thin
IDS_WIDTH_THIN Thin
IDS_WIDTH_MEDIUM Medium
IDS_WIDTH_THICK Thick
IDS_WIDTH_VTHICK Very Thick

Creating the Toolbar Combo Box

Before you can add the combo box to the color toolbar, you need to create a combo box variable that you can use for the combo box. Because you are not able to add this combo box through any of the designers, you need to add it as a variable to the CMainFrame class.

To add the combo box variable to the main frame class for the color toolbar, select the Class View tab in the workspace pane. Right-click the CMainFrame class and select Add Member Variable from the pop-up menu. Specify the variable type as CComboBox, the name as m_ctlWidth, and the access as protected.

Once you add the combo box variable to the main frame class, you need to perform a series of actions, all once the toolbar has been created:

1. Set the width and the ID of the combo box place holder on the toolbar to the width and ID of the combo box.

2. Get the position of the toolbar placeholder and use it to size and position the combo box.

3. Create the combo box, specifying the toolbar as the parent window of the combo box.

4. Load the strings into the drop-down list on the combo box.

To organize this so that it doesn't get too messy, it might be advisable to move the creation of the color toolbar to its own function that can be called from the OnCreate function of the main frame class. To create this function, right-click the CMainFrame class in the workspace pane and select Add Member Function from the pop-up menu. Specify the function type as BOOL, the function description as CreateColorBar, and the access as public. Edit the new function, adding the code in Listing 12.5.

LISTING

Previous chapterNext chapterContents