Toolbar Controls


Toolbars provide a means for users to activate commands and tools contained in an application. To make your application user-friendly, design your toolbar to expose the key functionality of the application. The following topics discuss features to consider when planning a toolbar.

 

Creating a Toolbar

You can use two functions to create a toolbar— CreateToolbarEx or CreateWindowEx . The CreateToolbarEx function creates a toolbar and adds an initial set of buttons to it. You can also use CreateWindowEx, specifying the TOOLBARCLASSNAME window class to create a toolbar that initially contains no buttons. The TOOLBARCLASSNAME window class is registered when the common control dynamic-link library (DLL) is loaded. To ensure that this DLL is loaded, use the InitCommonControlsEx function first. If you create an empty toolbar, you add buttons to it by using the TB_ADDBUTTONS or TB_INSERTBUTTON message. If you retrieve the size of the toolbar, you must send the TB_AUTOSIZE message after all the items and strings have been inserted into the control to cause the toolbar to recalculate its size based on its content.

Specifying Toolbar Size and Position

If you create a toolbar using CreateToolbarEx, the function enables you to specify in pixels the height and width of the toolbar. However, the CreateWindowEx function does not have parameters for specifying toolbar size. The toolbar window procedure automatically sets the size and position of the toolbar window. The height is based on the height of the buttons in the toolbar. The width is the same as the width of the parent window's client area. To change the automatic size settings, send a TB_SETBUTTONSIZE message. The CCS_TOP and CCS_BOTTOM common control styles determine whether the toolbar is positioned along the top or bottom of the client area. By default, a toolbar has the CCS_TOP style.

Also, the toolbar window procedure automatically adjusts the size of the toolbar whenever it receives a WM_SIZE or TB_AUTOSIZE message. An application should send either of these messages whenever the size of the parent window changes or after sending a message that requires adjusting the size of the toolbar—for example, a TB_SETBUTTONSIZE message.

The toolbar default sizing and positioning behaviors can be turned off by setting the CCS_NORESIZE and CCS_NOPARENTALIGN common control styles. Toolbar controls that are hosted by rebar controls must set these styles because the rebar control sizes and positions the toolbar.

Displaying ToolTips for Buttons

When you specify the TBSTYLE_TOOLTIPS style, the toolbar creates and manages a ToolTip control. A ToolTip control is a small pop-up window that contains a line of text describing a toolbar button. The ToolTip control is hidden and appears only when the user moves the pointer over a toolbar button and leaves it there for approximately one second. The ToolTip control is displayed near the pointer.

When the toolbar receives a WM_MOUSEMOVE message, it sends a notification message to the ToolTip control. The ToolTip control sets a timer and, after approximately one second, checks to see if the pointer is still at the same location and is on a toolbar button. If it is, the ToolTip control sends a TTN_GETDISPINFO notification message to the parent window to retrieve the descriptive text for the button. Then the ToolTip control creates a pop-up window and displays the text in the window. The ToolTip control destroys the pop-up window when the user clicks a mouse button or moves the pointer out of the toolbar.

An application that needs to send messages directly to the ToolTip control can retrieve the handle to the control by using the TB_GETTOOLTIPS message. An application can replace the ToolTip control of a toolbar with another ToolTip control by using the TB_SETTOOLTIPS message.

Defining Button Images

There are two ways to specify the images for buttons—by bitmaps or by image lists. An application must choose which method to use. It cannot use both methods with the same toolbar control. Note that the CreateToolbarEx function uses the bitmap method. Applications that want to use the image list method must use the CreateWindowEx function to create the toolbar control.

Defining Button Images by Using Bitmaps

Each button in a toolbar can include a bitmapped image. A toolbar uses an internal list to store the information that it needs to draw the images. When you call the CreateToolbarEx function, you specify a monochrome or color bitmap that contains the initial images, and the toolbar adds the information to the internal list of images. You can add additional images later by using the TB_ADDBITMAP message.

Each image has a zero-based index. The first image added to the internal list has an index of 0, the second image has an index of 1, and so on. TB_ADDBITMAP adds images to the end of the list and returns the index of the first new image that it added. To associate the image with a button, you must send a TB_ADDBUTTONS message and specify the image's index after you add bitmaps to the internal image list.

Microsoft® Windows® assumes that all of a toolbar's bitmapped images are the same size. You specify the size when you create the toolbar by using CreateToolbarEx. If you use the CreateWindowEx function to create a toolbar, the size of the images is set to the default dimensions of 16 by 15 pixels. You can use the TB_SETBITMAPSIZE message to change the dimensions of the bitmapped images, but you must do so before adding any images to the internal list.

Defining Button Images by Using Image Lists

You can also store button images in a set of Image Lists . An image list is a collection of images of the same size, each of which can be referred to by its index. Image lists are used to manage large sets of icons or bitmaps. You can use up to three different image lists to display buttons in various states, as shown in the following table.

Normal Buttons in their default state.
Hot Buttons that are under the pointer or pressed. Hot items are supported only in toolbar controls that have the TBSTYLE_FLAT style.
Disabled Buttons that are disabled.

After the toolbar is destroyed, applications must free any image lists they have created.

Defining Text for Buttons

Each button can display a string in addition to, or instead of, an image. A toolbar maintains an internal list that contains all the strings available to toolbar buttons. You add strings to the internal list by using the TB_ADDSTRING message, specifying the address of the buffer containing the strings to add. Each string must be null-terminated, and the last string must be terminated with two null characters.

Each string has a zero-based index. The first string added to the internal list of strings has an index of 0, the second string has an index of 1, and so on. TB_ADDSTRING adds strings to the end of the list and returns the index of the first new string. You use a string's index to associate the string with a button.

Using TB_ADDSTRING is not the only way to add strings to a toolbar. You can display a string in a button by passing a string pointer in the iString field of the TBBUTTON structure that is passed to TB_ADDBUTTONS. Additionally, you can use TB_SETBUTTONINFO to assign text to a toolbar button. For more information, see Assigning text to a toolbar button .

Adding Toolbar Buttons

If you use the CreateToolbarEx function to create a toolbar, you can add buttons to the toolbar by filling an array of TBBUTTON structures and specifying the address of the array in the function call. However, the CreateWindowEx function does not have a parameter for passing a TBBUTTON structure. CreateWindowEx creates an empty toolbar that you fill by sending a TB_ADDBUTTONS message, specifying the address of a TBBUTTON structure.

After a toolbar is created, you can insert buttons by sending a TB_INSERTBUTTON message, which passes the address of a TBBUTTON structure to the toolbar. Each TBBUTTON structure defines the attributes of a button, including the indexes of its string and bitmap as well as its style, state, command identifier, and application-defined 32-bit value.

Note  If you use the CreateWindowEx function to create a toolbar, you must send the TB_BUTTONSTRUCTSIZE message before adding any buttons. The message passes the size of the TBBUTTON structure to the toolbar.

Toolbar Button Styles

A button's style determines how the button appears and how it responds to user input. For instance, the BTNS_BUTTON style creates a toolbar button that behaves like a standard push button. A button that has the BTNS_CHECK style is similar to a standard push button, except it toggles between the pressed and nonpressed states each time the user clicks it.

You can create groups of toolbar buttons that act like radio buttons by using the BTNS_GROUP or BTNS_CHECKGROUP style. This causes a button to stay pressed until the user chooses another button in the group. A group is defined as a contiguous collection of buttons, all with the BTNS_GROUP or BTNS_CHECKGROUP style.

The BTNS_SEP style creates a small gap between buttons or draws an etch between buttons on flat toolbars. A button with the BTNS_SEP style does not receive user input.

Version 5.80 of the common controls introduced some new toolbar button styles and renamed some of the older styles. All button style flags now begin with BTNS_XXX instead of TBSTYLE_XXX. For a listing and discussion of the button styles, see Toolbar Control and Button Styles .

Toolbar Button States

Each button in a toolbar has a state. The toolbar updates a button's state to reflect user actions, such as clicking the button. The state indicates whether the button is currently pressed or not pressed, enabled or disabled, hidden or visible. Although an application sets a button's initial state when adding the button to the toolbar, it can change and retrieve the state by sending TB_GETSTATE and TB_SETSTATE messages to the toolbar. For a list of toolbar button states, see Toolbar States .

Command Identifier

Each button has an application-defined command identifier associated with it. Button identifiers are usually defined in an application header file. For example, a Paste button can be defined as:

#define ID_PASTE 100

When the user selects a button, the toolbar sends the parent window a WM_COMMAND or WM_NOTIFY message that includes the command identifier of the button. The parent window examines the command identifier and carries out the command associated with the button. For information about when controls send WM_COMMAND messages and when they send WM_NOTIFY, see the Remarks section of the WM_NOTIFY documentation.

Button Size and Position

A toolbar keeps track of its buttons by assigning each button a position index. The index is zero-based; that is, the leftmost button has an index of 0, the next button to the right has an index of 1, and so on. An application must specify the index of a button when sending messages to retrieve information about the button or to set the button's attributes.

A toolbar updates the position indexes as buttons are inserted and removed. An application can retrieve the current position index of a button by using the TB_COMMANDTOINDEX message. The message specifies the command identifier of a button, and the toolbar window uses the identifier to locate the button and return its position index.

All buttons in a toolbar are the same size. The CreateToolbarEx function requires you to set the initial size of the buttons when you create the toolbar. When you use the CreateWindowEx function, the initial size is set to the default dimensions of 24 by 22 pixels. You can use the TB_SETBUTTONSIZE message to change the button size, but you must do so before adding any buttons to the toolbar. The TB_GETITEMRECT message retrieves the current dimensions of the buttons.

When you add a string that is longer than any string currently in the toolbar, the toolbar automatically resets the width of its buttons. The width is set to accommodate the longest string in the toolbar.

Customizing a Toolbar

A toolbar has built-in customization features that you can make available to the user by giving the toolbar the CCS_ADJUSTABLE common control style. The customization features allow the user to drag a button to a new position or to remove a button by dragging it off the toolbar. In addition, the user can double-click the toolbar to display the Customize Toolbar dialog box, which allows the user to add, delete, and rearrange toolbar buttons. To display the dialog box, use the TB_CUSTOMIZE message. An application determines whether the customization features are available to the user and controls the extent to which the user can customize the toolbar.

As part of the customization process, applications often need to save and restore a toolbar's state. For instance, many applications store the toolbar state before the user begins customizing the toolbar in case the user later wants to restore the toolbar to its original state. The toolbar control does not automatically keep a record of its precustomization state. Your application must save the toolbar state in order to restore it. For more information, see Customizing Toolbars and Using Hot-tracking with Toolbars .

Using Hot-tracking

Toolbar controls created with the TBSTYLE_FLAT style support hot-tracking by default. Hot-tracking means that when the pointer moves over an item, it is highlighted but not selected. When the user moves the pointer over a toolbar button, the button's appearance changes. You can use other window styles in combination with TBSTYLE_FLAT to produce toolbars that enable hot-tracking but have a different appearance from a flat toolbar. For more information, see Using Hot-tracking with Toolbars .

Using Toolbar Frames

Toolbar frames serve as containers for toolbars and other child windows. You implement toolbar frames by creating a rebar control and adding one or more controls to it. A rebar control hosts one or more bands. Each band contains only one child window.

Rebar controls are separate controls but they are often used to host toolbar controls. Using toolbar and rebar controls together enables you to write applications that are more flexible. For example, toolbars can be moved, repositioned, minimized, and maximized within the rebar control. For more information about programming rebar controls, see Rebar Controls .

Using Toolbar Controls


This section contains examples that demonstrate how to create and use toolbar controls in your applications.

Creating Toolbars

You can use two functions to create a toolbar— CreateWindowEx or CreateToolbarEx . This topic provides code samples using the two functions and also discusses several ways to add text to toolbar buttons.

Creating a Toolbar with CreateWindowEx

The following CreateAToolBar sample function uses CreateWindowEx and specifies the TOOLBARCLASSNAME window class to create an empty toolbar. To add buttons and button strings to the toolbar, the function uses TB_ADDSTRING and TB_ADDBUTTONS messages.

Assigning text to a toolbar button

You are not required to make an internal list of strings to add text to a button. There are alternative methods. One alternative is to pass a string pointer to the iString member of a TBBUTTON structure. For example, you can place text in a buffer, retrieve a pointer to the buffer, enter the pointer in a TBBUTTON structure, and send a TB_ADDBUTTONS message, specifying the filled TBBUTTON structure.

tbb[0].iBitmap = -1; 
tbb[0].idCommand = IDS_CUT; 
tbb[0].fsState = TBSTATE_ENABLED; 
tbb[0].fsStyle = TBSTYLE_BUTTON; 
tbb[0].dwData = 0; 
tbb[0].iString = (int) pszBuf;  // Text is in a buffer.

Another way to assign text to a button is with the TB_SETBUTTONINFO message. You enter the data you want to change in a TBBUTTONINFO structure. Then send a TB_SETBUTTONINFO message. The following example demonstrates how to modify the previous CreateAToolBar code to change the text of the third button from Paste to Change.

char szBuf[8] = "CHANGE";
LPSTR pszBuf;
TBBUTTONINFO tbi;
LPTBBUTTONINFO lptbbi;

// Other code here.
// Initialize pszBuf and lptbbi.

// These are the only fields of the TBBUTTONINFO structure that 
// need to be changed to modify text.   
	tbi.dwMask = TBIF_TEXT;
	tbi.cbSize = sizeof (TBBUTTONINFO);
	tbi.pszText = pszBuf;
	tbi.cchText = sizeof (szBuf);
SendMessage(hwndTB, TB_SETBUTTONINFO, IDS_PASTE, (LPARAM)
    (LPTBBUTTONINFO)lptbbi);

 

Note   If you change a button's text by using TB_SETBUTTONINFO, this does not affect the string assigned to that button in the internal string list. Also, if you add a toolbar button string to the internal text list, you cannot retrieve the index of that string by calling TBN_GETBUTTONINFO ; you must use TB_GETBUTTON instead.

Creating a Toolbar with CreateToolbarEx

This example uses CreateToolbarEx to create a toolbar and adds standard bitmaps to the toolbar. The standard toolbar bitmaps are built into Comctl32.dll. You do not have to use the standard bitmaps; you can use your own custom bitmaps. To add a bitmap to an application, use the TB_ADDBITMAP message. The sample function, CreateAToolBar2, adds three standard file bitmaps and four standard view bitmaps. Because CreateAToolBar2 requires a TBBUTTON structure containing the predefined indexes to the bitmaps, you must include the following TBBUTTON structures in your application.

Show Example

Creating Transparent Toolbars

Toolbar controls support a transparent look that allows the client area under the toolbar to show through. There are two kinds of transparent toolbars, ones with flat buttons and ones with three-dimensional buttons. If you want your application to match the Microsoft® Windows® interface, use the flat transparent style toolbar. You create a flat transparent toolbar by including the TBSTYLE_FLAT style. To create a nonflat transparent toolbar, use TBSTYLE_TRANSPARENT . The following illustration shows the two kinds of transparent toolbars. The flat transparent toolbar was created with the TBSTYLE_FLAT style; the nonflat transparent toolbar was created with the TBSTYLE_TRANSPARENT style.

To create a transparent toolbar, all you need to do is add TBSTYLE_FLAT or TBSTYLE_TRANSPARENT to the window style parameter of CreateToolbarEx . If you do not want a line to appear to indicate the bottom of the toolbar, do not use the WS_BORDER window style. The following code snippet shows a call to CreateToolbarEx that produces a transparent toolbar with flat buttons.

hWndToolbar = CreateToolbarEx (hWndParent, 
    WS_CHILD | WS_VISIBLE | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT, 
    ID_TOOLBAR, 11, (HINSTANCE)HINST_COMMCTRL, IDB_STD_SMALL_COLOR, 
    (LPCTBBUTTON)&tbButtons, 4, 0, 0, 100, 30, sizeof (TBBUTTON));

To produce a transparent toolbar with raised buttons, change TBSTYLE_FLAT to TBSTYLE_TRANSPARENT.

Creating List-style Toolbars

Toolbar buttons enable you to display both text and bitmaps. The buttons on a toolbar created with the TBSTYLE_LIST style are different from other toolbar buttons because they place text to the right of the bitmap instead of under the image. Also, the list-style button leaves a blank space if you fail to provide images or text; other buttons do not. You can use the TBSTYLE_LIST toolbar style in combination with the TBSTYLE_FLAT style to create a toolbar with flat buttons. The following illustration shows two list-style toolbars that have buttons with both text and bitmaps. The list toolbar was created with the TBSTYLE_LIST style; the flat list toolbar was created with both the TBSTYLE_LIST and TBSTYLE_FLAT styles.

The following code snippet creates a toolbar with the TBSTYLE_LIST style.

hWndToolbar = CreateToolbarEx (hWndParent, 
    WS_CHILD | WS_VISIBLE | TBSTYLE_TOOLTIPS | TBSTYLE_LIST, 
    ID_TOOLBAR, 11, (HINSTANCE)HINST_COMMCTRL, IDB_STD_SMALL_COLOR, 
    (LPCTBBUTTON)&tbButtons, 4, 0, 0, 100, 30, sizeof (TBBUTTON));

To create a flat list-style toolbar, use the following:

hWndToolbar = CreateToolbarEx (hWndParent, 
    WS_CHILD | WS_VISIBLE | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT |
    TBSTYLE_LIST, ID_TOOLBAR, 11, (HINSTANCE)HINST_COMMCTRL,
    IDB_STD_SMALL_COLOR, (LPCTBBUTTON)&tbButtons, 4, 0, 0, 100, 
    30, sizeof (TBBUTTON));

When you create a list-style toolbar, you should provide text and bitmaps to avoid blank spaces on the button. For information about adding text and bitmaps to a button, see Assigning text to a toolbar button and Defining Button Bitmaps.

Handling ToolTips

Applications that need to customize the text displayed in toolbar ToolTips must respond to the TTN_GETDISPINFO message sent by the toolbar control to its parent, rather than subclassing the toolbar control and intercepting the notification from the ToolTip to the toolbar. The method by which the toolbar and its associated ToolTip communicate varies from platform to platform.

A toolbar that has the TBSTYLE_TOOLTIPS style creates a ToolTip control, which an application can use to display Help text for toolbar buttons. The parent window receives the TTN_GETDISPINFO notification message when the toolbar needs the Help text for a button. The ToolTip control sends the notification in the form of a WM_NOTIFY message. The lParam parameter includes the address of an NMTTDISPINFO structure that specifies the command identifier of the button for which Help text is needed. An application can copy the Help text to the structure, specify the address of a string containing the Help text, or specify the instance handle and resource identifier of a string resource.

The following example specifies an instance handle and a resource identifier to handle the TTN_GETDISPINFO ToolTip notification.

Show Example

If an application specifies labels in the iString member of the associated TBBUTTON structure, the toolbar control automatically uses that string as the ToolTip. You must send a TB_SETMAXTEXTROWS message and set the maximum text rows to zero to keep the label from appearing on the button. If your application does not respond to TTN_GETDISPINFO, the toolbar uses the label as the ToolTip text.

You can also provide ToolTips by using the TBSTYLE_EX_MIXEDBUTTONS extended style. This style allows you to set text for all buttons, but only display it for those buttons with the BTNS_SHOWTEXT button style. The TBSTYLE_LIST style must also be set. Normally, when a button does not display text, your application must handle TBN_GETINFOTIP to display a ToolTip. With the TBSTYLE_EX_MIXEDBUTTONS extended style, text that is set but not displayed on a button will automatically be used as the button's ToolTip text. Your application needs to handle TBN_GETINFOTIP only if it needs more flexibility in specifying the ToolTip text.

Handling Drop-down Buttons

A drop-down button is designed to present users with a list of options. You create this style button by specifying the BTNS_DROPDOWN style, also called TBSTYLE_DROPDOWN for compatibility with previous versions of the common controls. To produce a drop-down button with an arrow displayed on the right, you must specify BTNS_DROPDOWN and set the TBSTYLE_EX_DRAWDDARROWS toolbar style by sending a TB_SETEXTENDEDSTYLE message. The following illustration shows the two kinds of drop-down buttons. The toolbar with the drop-down button was created with the BTNS_DROPDOWN button style; the toolbar with the drop-down button and arrow was created with the BTNS_DROPDOWN button style and the TBSTYLE_EX_DRAWDDARROWS toolbar style.

When the user clicks a toolbar button that uses the BTNS_DROPDOWN style, the toolbar control sends its parent a TBN_DROPDOWN notification message. The application's notification handler can then display a list of options. When you click a drop-down arrow button, a TBN_DROPDOWN notification is sent; if you click the associated arrow, a WM_COMMAND message is sent.

An application can support a drop-down button in a toolbar control, as illustrated in the following DoNotify application-defined function:

 

Customizing Toolbars

Most Windows-based applications use toolbar controls to provide their users with convenient access to various tools. However, static toolbars have some shortcomings, such as too little space to effectively display all the available tools.

The solution to this problem is to make your application's toolbars customizable. Users can then move, add, and delete tools to select only the ones they need and organize them in whatever way they find convenient.

To enable customization, include the CCS_ADJUSTABLE common controls style flag when you create the toolbar control. There are two basic approaches to customization:

You can implement either or both, depending on the needs of the application. Neither of these two approaches to customization provides a built-in mechanism, such as a Cancel or Undo button, to return the toolbar to its former state. You must explicitly use the toolbar control API to store the toolbar's precustomization state. If necessary, you can later use this stored information to restore the toolbar to its original state.

This topic discusses how to enable toolbar customization with the customization dialog box and with drag and drop.

Customization Dialog Box

The customization dialog box is provided by the toolbar control to give users a simple way to add, move, or delete tools. Users can launch it by double-clicking the toolbar. Applications can launch the customization dialog box by sending the toolbar control a TB_CUSTOMIZE message. The following illustration shows an example of the toolbar customization dialog box.

The tools in the right-hand list box are those currently on the toolbar. Initially, this list will contain the tools that you specify when you create the toolbar. The left-hand list box contains the tools that are available to add to the toolbar. Your application is responsible for populating that list and keeping track of what tools are currently on the toolbar.

Implementing the customization dialog box

The toolbar control notifies your application that it is launching a customization dialog box by sending its parent window a TBN_BEGINADJUST notification. It then sends a TBN_INITCUSTOMIZE notification. If you don't want the toolbar to display a Help button, handle this notification and return TBNRF_HIDEHELP.

The toolbar control then collects the information it needs to initialize the dialog box by sending three series of notifications in the following order:

The dialog box is then displayed, and the user can begin to customize the toolbar.

Once the dialog box is displayed, your application can receive a variety of notifications, depending on the users' actions:

After the dialog box is destroyed, your application will receive a TBN_ENDADJUST notification.

The following code example demonstrates how to handle notifications to enable toolbar customization.

Show Example

Dragging and Dropping Tools

Users can also rearrange the buttons on a toolbar by pressing the SHIFT key and dragging the button to another location. The drag-and-drop process is handled automatically by the toolbar control. It displays a ghost image of the button as it is dragged, and rearranges the toolbar after it is dropped. Users cannot add buttons in this way, but they can delete a button by dropping it off the toolbar.

Although the toolbar control normally does this operation automatically, it also sends your application two notifications: TBN_QUERYDELETE and TBN_QUERYINSERT. To control the drag-and-drop process, handle these notifications as follows:

If the user attempts to drag a button without also pressing the SHIFT key, the toolbar control will not handle the drag-and-drop operation. However, it will send your application a TBN_BEGINDRAG notification to indicate the start of a drag operation, and a TBN_ENDDRAG notification to indicate the end. If you want to enable this form of drag-and-drop, your application must handle these notifications, provide the necessary user interface, and modify the toolbar to reflect any changes.

Saving and Restoring Toolbars

In the process of customizing a toolbar, your application might need to save information so that you can restore the toolbar to its original state. To initiate saving or restoring a toolbar state, send the toolbar control a TB_SAVERESTORE message with the lParam set to TRUE. The lParam value of this message specifies whether you are requesting a save or a restore operation. Once the message is sent, there are two ways to handle the save/restore operation:

Toolbar states are saved in a data stream that consists of blocks of Shell-defined data alternating with blocks of application-defined data. One data block of each type is stored for each button, along with an optional block of global data that applications can place at the beginning of the stream. During the save process, your TBN_SAVE handler adds the application-defined blocks to the data stream. During the restore process, the TBN_RESTORE handler reads each block and gives the Shell the information it needs to reconstruct the toolbar.

How to Handle a TBN_SAVE Notification

The first TBN_SAVE notification is sent at the beginning of the save process. Before any buttons are saved, the members of the NMTBSAVE structure are set as shown in the following table.

Member Setting
iItem -1
cbData Amount of memory needed for Shell-defined data.
cButtons Number of buttons.
pData Calculated amount of memory needed for application-defined data. Typically, you include some global data, plus data for each button. Add that value to cbData and allocate enough memory to pData to hold it all.
pCurrent First unused byte in the data stream. If you do not require global toolbar information, set pCurrent = pData so that it points to the start of the data stream. If you do require global toolbar information, store it at pData, then set pCurrent to the beginning of the unused portion of the data stream before returning.

If you want to add some global toolbar information, put it at the start of the data stream. Advance pCurrent to the end of the global data so that it points to the beginning of the unused portion of the data stream, and return.

After you return, the Shell starts saving button information. It adds the Shell-defined data for the first button at pCurrent and then advances pCurrent to the start of the unused portion.

After each button is saved, a TBN_SAVE notification is sent and NMTBSAVE is returned with these members set as follows.

Member Setting
iItem Zero-based index of the button number.
pCurrent Pointer to the first unused byte in the data stream. If you want to store additional information about the button, store it at the location pointed to by pCurrent and update pCurrent to point to the first unused portion of the data stream after that.
TBBUTTON TBBUTTON structure that describes the button being saved.

When you receive the notification, you should extract any button-specific information you need fromTBBUTTON. Remember that when you add a button, you can use the dwData member of TBBUTTON to hold application-specific data. Load your data into the data stream at pCurrent. Advance pCurrent to the end of your data, again pointing to the beginning of the unused portion of the stream, and return.

The Shell then goes to the next button, adds its information to pData, advances pCurrent, loads TBBUTTON, and sends another NMTBSAVE notification. This process continues until all buttons are saved.

Restoring Saved Toolbars

The restore process basically reverses the save process. At the beginning, your application will receive a NMTBRESTORE notification with the iItem member of the NMTBRESTORE structure set to -1. The cbData member is set to the size ofpData, and cButtons is set to the number of buttons.

Your notification handler should extract the global information placed at the beginning of pData during the save, and advance pCurrent to the start of the first block of Shell-defined data. Set cBytesPerRecord to the size of the data blocks you used to save the button data. Set cButtons to the number of buttons, and return.

The next NMTBRESTORE is for the first button. The pCurrent member points to the start of your first block of button data, and iItem is to the button index. Extract that data and advance pCurrent. Load the data into TBBUTTON, and return. To omit a button from the restored toolbar, set the idCommand member of TBBUTTON to zero. The Shell will repeat the process for the remaining buttons.

In addition to NMTBSAVE and NMTBRESTORE messages, you can also use messages such as TBN_RESET to save and restore a toolbar. The following code snippet saves a toolbar before it is customized and restores it if the application receives a TBN_RESET message.

Embedding Nonbutton Controls in Toolbars

Toolbars support only buttons; therefore, if your application requires a different kind of control, you must create a child window. The following illustration shows a toolbar with an embedded edit control.

Any type of window can be placed on a toolbar. The following sample code adds an edit control as a child of the toolbar control window. Because the toolbar is created and then the edit control added, you must provide space for the edit control. One way to do this is to add a separator as a placeholder in the toolbar. For example, to add an edit control to the second code sample in the Creating Toolbars section of this article, you first add a separator to tbButtonsCreate, a customized TBBUTTON structure. You set the width of the separator to the number of pixels you want to reserve.

The following application-defined function creates the toolbar, and adds the buttons and the edit control.

The sample hard-codes the dimensions of the child window; however, to make a more robust application, determine the size of the toolbar and make the edit control window to fit.

You might want the edit control notifications to go to another window, such as the toolbar's parent. To do this, create the edit control as a child of the toolbar's parent window. Then change the parent of the edit control to the toolbar. Notifications go to the original parent; therefore, the edit control messages go to the parent of the toolbar and yet the edit window resides in the toolbar window. The following code example demonstrates this.

// Create the edit control. Notice that hWndParent, parent of
// the toolbar, is used as the parent of the edit control.    
hWndEdit = CreateWindowEx(0L, "Edit", NULL, WS_CHILD | WS_BORDER
   | WS_VISIBLE | ES_LEFT | ES_AUTOVSCROLL | ES_MULTILINE, 
   0, 0, cx_edit, cy_edit, hWndParent, (HMENU) IDM_EDIT, hInst, 0 );
   
// Set the toolbar window as the parent of the edit control
// window. You must set the toolbar as the parent of the edit
// control for it to appear embedded in the toolbar.
SetParent (hWndEdit, hWndToolbar);    

Using Hot-tracking with Toolbars

When a mouse pointer hovers over an item, the item becomes hot. If hot-tracking is enabled, the hot item is selected and the item under the mouse pointer is highlighted. Hot-tracking is supported by common controls, such as the toolbar, list view, tab, and header. Some controls have window styles that provide hot-tracking by default; others require that a specific hot-tracking window style be used. A toolbar created with the TBSTYLE_FLAT style supports hot-tracking by default. You can use TBSTYLE_FLAT in combination with other window styles to produce toolbars that enable hot-tracking. Hot-tracking requires that you create image lists; therefore, you cannot use TB_ADDBITMAP or CreateToolbarEx to create your toolbar.

When the mouse hovers over a toolbar button, the button is outlined to highlight it. The following illustration shows a flat or transparent toolbar with hot-tracking enabled.

If you want a toolbar button bitmap to change when the state of the control changes, store the different images in Image Lists . For example, some applications have black and white toolbar buttons that become colored when they are selected. The two different images are stored in image lists. Toolbars support using up to three image lists. Typically an application has a default, disabled, and hot-tracking list of images. To set and retrieve image lists for hot toolbar buttons, use TB_SETHOTIMAGELIST and TB_GETHOTIMAGELIST . The following code snippet creates, fills, and assigns an image list for hot buttons.



© 2002 Microsoft Corporation. All rights reserved.