Objective Toolkit : Chapter 6 Customizable Toolbars : Using the Customizable Toolbar Classes
Using the Customizable Toolbar Classes
The following sections describe how to use customizable tooltips in your applications.
To incorporate customizable toolbars into your application
1. Generate a skeletal application with toolbars using AppWizard.
If you create a
Do this
MDI application
Replace CMDIFrameWnd with SECMDIFrameWnd. Replace CMDIChildWnd with SECMDIChildWnd.
SDI application
Replace CFrameWnd with SECFrameWnd.
2. Replace CToolBar or SECToolbar with SECCustomToolBar. ReplaceCStatusBar with SECStatusBar.
3. Use the Microsoft Visual Studio toolbar resource editor to create a composite bitmap of all the toolbar buttons you want to use with any of the customizable toolbars as one resource. Do NOT put any button separators inside this toolbar resource. Specify every button command ID you want to associate with a bitmap in the resource editor.
4. You can also create a copy of the previous resource and set a larger pixel height/width and redraw any bitmap images as you see fit. This is your large buttons resource. It is important that you maintain a 1-1 button ID mapping to the resource you created earlier. This is essentially a different view of the same data.
5. In your CMainFrame constructor, create the SECToolBarManager object. Use the existing m_pControlBarManager member from the frame’s base class. For example:
 
m_pControlBarManager = new SECToolBarManager(this);
6. In CMainFrame::OnCreate(), issue a call to LoadToolBarResource to load the resource(s) created earlier. If you're only using one resource, use the same resource ID twice. For example,
 
// large and small resources
pToolBarMgr-> LoadToolBarResource(MAKEINTRESOURCE(IDR_MAINFRAME),
MAKEINTRESOURCE(IDR_MAINFRAME_LG)));
 
// OR small resources only (identical views)
pToolBarMgr-> LoadToolBarResource(MAKEINTRESOURCE(IDR_MAINFRAME),
MAKEINTRESOURCE(IDR_MAINFRAME)));
 
m_pControlBarManager is declared as type SECControlBarManager so you must typecast to SECToolBarManager to access the specific member function mentioned above. For example,
 
SECToolBarManager* pToolBarMgr=
(SECToolBarManager *)m_pControlBarManager;
7. Create a button group. For example:
 
static UINT BASED_CODE fileButtons[] =
{
ID_FILE_NEW,
ID_FILE_OPEN,
ID_FILE_SAVE,
ID_FILE_SAVEALL,
};
See “To implement button groups”for more information.
8. In CMainFrame::OnCreate(), define default toolbar resources via the DefineDefaultToolBar() method. For example,
 
pToolBarManager->DefineDefaultToolBar(AFX_IDW_TOOLBAR,
_T("File"),NUMELEMENTS(fileButtons),fileButtons,
CBRS_ALIGN_ANY,AFX_IDW_DOCKBAR_TOP);
NOTE >> Toolbar IDs AFX_IDW_TOOLBAR+1,+2,+3 are reserved by other MFC components, including the status bar, and cannot be used in this call. However, you can use +0, +4 and higher.
9. If you do not plan to load toolbar states from persistent storage, call the toolbar manager’s SetDefaultDockState() method to pre-load the default toolbars in your application. For example:
 
pToolBarMgr->SetDefaultDockState();
See “To use the button map” “To save and restore customizable toolbars” and ““To implement the toolbar customization dialog.”
To implement toolbars with the flat cool look with a toolbar manager
In the OnCreate() method of your main frame class, call the EnableCoolLook() method of the toolbar manager. For example:
 
// the boring old toolbars won't cut it, let's see something cool!
pToolBarMgr->EnableCoolLook(TRUE);
To implement toolbars with the flat cool look without a toolbar manager
1. Generate a skeletal application with toolbars.
If you create a
Do this
MDI application
Replace CMDIFrameWnd with SECMDIFrameWnd.
Replace CMDIChildWnd with SECMDIChildWnd.
SDI application
Replace CFrameWnd with SECFrameWnd.
2. Replace CToolBar or SECToolbar with SECCustomToolBar and CStatusBar with SECStatusBar.
3. Change the toolbar create syntax to that of the SECCustomToolBar create overload and specific the cool extended styles. For example:
 
if(!m_wndToolBar.CreateEx(CBRS_EX_COOLBORDERS|CBRS_EX_GRIPPER,this) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
 
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
To implement button groups
1. Create the button group as a static array using the button control IDs defined with the associated bitmap resource in the Resource Editor. For example:
 
static UINT BASED_CODE fileButtons[] =
{
ID_FILE_NEW,
ID_FILE_OPEN,
ID_FILE_SAVE,
ID_FILE_SAVEALL,
};
2. In CMainFrame::OnCreate(), define the default toolbar using the DefineDefaultToolBar() method. For example:
 
SECToolBarManager* pToolBarMgr=
(SECToolBarManager *)m_pControlBarManager;
pToolBarManager-> DefineDefaultToolBar(AFX_IDW_TOOLBAR,
_T("File"),NUMELEMENTS(fileButtons),fileButtons,
CBRS_ALIGN_ANY,AFX_IDW_DOCKBAR_TOP);
NOTE >> Toolbar Ids AFX_IDW_TOOLBAR+1,+2,+3 are reserved by other MFC components, including the status bar and cannot be used in this call. However, you can use +0, +4 and higher.
To use multiple toolbar bitmap resources with the toolbar manager
Use the SECToolBarManager::AddToolBarResource() method in conjunction with LoadToolBarResource(). For example:
 
// Use the following calls for multiple bitmaps
// (to surpass the 2048 pixel width limit on toolbar bitmaps)
pToolbarManager->AddToolBarResource(
MAKEINTRESOURCE(IDR_MAINFRAME1),
MAKEINTRESOURCE(IDR_MAINFRAMELARGE1));
pToolbarManager->AddToolBarResource(
MAKEINTRESOURCE(IDR_MAINFRAME2),
MAKEINTRESOURCE(IDR_MAINFRAMELARGE2));
VERIFY(pMgr->LoadToolBarResource());
To find a button on a customizable toolbar
1. Obtain a pointer to the customizable toolbar. See “To obtain a pointer to a specific customizable toolbar” for more information.
2. For each customizable toolbar, use the GetBtnCount() method and the m_btns data member to access the button data.
NOTE >> If your application contains the Customize dialog, you may have more than one copy of that button in existence.
For example:
 
// Get pointer to custom toolbar using the preceding
// procedure…
int nButtons=pBar->GetBtnCount();
 
for(int nIndex=0;nIndex<nButtons;++nIndex)
{
if(m_btns[nIndex]->m_nID==MY_TARGET_ID)
 
}
To use the button map
The button map maps specific button command IDs to non-standard toolbar buttons.
1. Create a customizable toolbar that uses a toolbar manager. See “To incorporate customizable toolbars into your application” for more information.
2. Create a button map in your frame class implementation file. For example:
 
BEGIN_BUTTON_MAP(btnMap)
STD_BUTTON(ID_CHECKED, TBBS_CHECKBOX)
STD_BUTTON(ID_DISABLE, TBBS_CHECKBOX)
STD_BUTTON(ID_INDETERMINATE, TBBS_INDETERMINATE)
TWOPART_BUTTON(ID_UNDO, ID_DROPARROW, \
TBBS_CHECKBOX, 0)
TWOPART_BUTTON(ID_REDO, ID_DROPARROW, 0, \
ID_REDO)
COMBO_BUTTON(ID_FIND, IDC_COMBO_FIND, 0, \
CBS_DROPDOWN, 150, 40, 150)
END_BUTTON_MAP()
3. In the frame’s OnCreate() method, provide a reference to the button map using the toolbar manager’s SetButtonMap() method. For example,
 
pMgr->SetButtonMap(btnMap);
To implement a text button
1. Create a customizable toolbar that uses a toolbar manager. See “To incorporate customizable toolbars into your application” for more information.
2. Create a button map with a TEXT_BUTTON macro entry in your frame class implementation file. For example:
 
BEGIN_BUTTON_MAP(btnMap)
TEXT_BUTTON(ID_TEXTBTN, IDS_BUTTONTEXT)
END_BUTTON_MAP()
3. In the frame’s OnCreate() method, provide a reference to the button map using the toolbar manager’s SetButtonMap() method. For example:
 
pMgr->SetButtonMap(btnMap);
To implement a text button with styles
1. Create a customizable toolbar that uses a toolbar manager. See “To incorporate customizable toolbars into your application” for more information.
2. Create a button map with a TEXT_BUTTON_EX macro entry in your frame class implementation file. For example:
 
BEGIN_BUTTON_MAP(btnMap)
TEXT_BUTTON_EX(ID_TEXTBTN, IDS_BUTTONTEXT, \
TBBS_CHECKBOX)
END_BUTTON_MAP()
3. In the frame’s OnCreate() method, provide a reference to the button map using the toolbar manager’s SetButtonMap() method. For example:
 
pMgr->SetButtonMap(btnMap);
To implement a combo button
1. Create a customizable toolbar that uses a toolbar manager. See “To incorporate customizable toolbars into your application” for more information.
2. Create a button map with a COMBO_BUTTON macro entry in your frame class implementation file. For example:
 
BEGIN_BUTTON_MAP(btnMap)
COMBO_BUTTON(ID_FIND, IDC_COMBO_FIND, 0,
CBS_DROPDOWN, 150, 40, 150)
END_BUTTON_MAP()
3. In the frame’s OnCreate() method, provide a reference to the button map using the toolbar manager’s SetButtonMap() method. For example:
 
pMgr->SetButtonMap(btnMap);
To implement a twopart button
1. Create a customizable toolbar that uses a toolbar manager. See “To incorporate customizable toolbars into your application” for more information.
2. Create a button map with a TWOPART_BUTTON macro entry in your frame class implementation file. For example:
 
BEGIN_BUTTON_MAP(btnMap)
TWOPART_BUTTON(ID_UNDO, ID_DROPARROW, \
TBBS_CHECKBOX, 0)
END_BUTTON_MAP()
3. In the frame’s OnCreate() method, provide a reference to the button map using the SetButtonMap() method. For example:
 
pMgr->SetButtonMap(btnMap);
To implement a bitmap button using styles
1. Create a customizable toolbar that uses a toolbar manager. See “To incorporate customizable toolbars into your application” for more information.
2. Create a button map with a STD_BUTTON macro entry in your frame class implementation file. For example:
 
BEGIN_BUTTON_MAP(btnMap)
STD_BUTTON(ID_DISABLE, TBBS_CHECKBOX)
END_BUTTON_MAP()
3. In the frame’s OnCreate() method, provide a reference to the button map using the SetButtonMap() method. For example:
 
pMgr->SetButtonMap(btnMap);
To make a customizable toolbar dockable
When you define toolbars with the toolbar manager, specify the docking behavior as parameters in the DefineDefaultToolbar() method. For example:
 
pToolBarManager-> DefineDefaultToolBar(AFX_IDW_TOOLBAR,
_T("File"),NUMELEMENTS(fileButtons),fileButtons,
CBRS_ALIGN_ANY,AFX_IDW_DOCKBAR_TOP);
 
// Call this to position the default toolbars as
// configured by the DefineDefaultToolBar command
// above. Don't do this if you are going use
// LoadBarState/LoadState below, as these functions
// will call it anyways on nonexistent state info.
pToolBarMgr->SetDefaultDockState();
To reposition customizable toolbars at run time
1. Obtain a pointer to the customizable toolbar. See “To obtain a pointer to a specific customizable toolbar” and “To iterate the customizable toolbars”.
2. After you identify a controlbar as a customizable toolbar, use the DockControlBarEx member of CFrameWnd to modify the position of the toolbar. For example:
 
DockControlBarEx(pBar, AFX_IDW_DOCKBAR_RIGHT);
To obtain a pointer to a specific customizable toolbar
Use the CFrameWnd::GetControlBar() method. Pass the ID of the toolbar you want to access as a parameter. For example,
 
SECCustomToolBar* pBar = STATIC_DOWNCAST( SECCustomToolBar,
GetControlBar(AFX_IDW_TOOLBAR));
To iterate the customizable toolbars
Use the m_listControlBars member of the SECFrameWnd or SECMDIFrameWnd class declared as a CPtrList to iterate through the configured controlbars of the frame window:
 
CControlBar* pBar;
POSITION pos=m_listControlBars.GetHeadPosition();
 
while(pos)
{
pBar=(CControlBar*) m_listControlBars.GetNext(pos);
 
if(pBar-> IsKindOf(RUNTIME_CLASS(SECCustomToolBar)))
{
// do something with this custom toolbar
}
}
To implement the toolbar customization dialog
1. Incorporate toolbars with a toolbar manager. See “To incorporate customizable toolbars into your application”for more information.
2. Create a handler method in which to instantiate the Customization dialog. For example:
 
void CMainFrame::OnCustomize()
{
}
3. Within the handler, instantiate a property sheet of type SECToolBarSheet. For example:
 
SECToolBarSheet toolbarSheet;
4. If you need a toolbar page that shows and hides toolbars, create a property page of type SECToolBarsPage. Then, add it to the property sheet after specifying the toolbar manager for the page. For example:
 
SECToolBarsPage toolbarPage;
toolbarPage.SetManager((SECToolBarManager*)m_pControlBarManager);
toolbarSheet.AddPage(&toolbarPage);
5. If you need a toolbar command page to drag-and-drop additional buttons onto toolbars, create a property page of SECToolBarCmdPage. Specify the toolbar manager, define the button groups, and add the page to the property sheet. For example:
 
SECToolBarCmdPage cmdPage(SECToolBarCmdPage::IDD,
IDS_COMMANDS);
cmdPage.SetManager((SECToolBarManager*)m_pControlBarManager);
cmdPage.DefineBtnGroup(_T("File"),
NUMELEMENTS(fileButtons),
fileButtons);
cmdPage.DefineBtnGroup(_T("Help"),
NUMELEMENTS(helpButtons),
helpButtons);
cmdPage.DefineBtnGroup(_T("Browse"),
NUMELEMENTS(browseButtons),
browseButtons);
cmdPage.DefineBtnGroup(_T("Debug"),
NUMELEMENTS(debugButtons),
debugButtons);
cmdPage.DefineBtnGroup(_T("Palette"),
NUMELEMENTS(paletteButtons),
paletteButtons);
cmdPage.DefineBtnGroup(_T("Resource"),
NUMELEMENTS(resourceButtons),
resourceButtons);
 
toolbarSheet.AddPage(&cmdPage);
6. You can add additional property pages to the property sheet. For example:
 
// We have a dummy page to demonstrate window activation
// handling when swapping to and from the toolbar page
CPropertyPage dummyPage(IDD_DUMMY);
toolbarSheet.AddPage(&dummyPage);
7. To invoke the dialog, call the DoModal() method:
 
toolbarSheet.DoModal();
To invoke the toolbar customization dialog with a toolbar button
1. Create a handler to create the toolbar Customize dialog. See “To implement the toolbar customization dialog” for more information.
2. Map a button event to an additional handler, which posts a message to the message queue to launch the toolbar Customization dialog. For example,
 
void CMainFrame::OnMyDialogButton()
{
PostMessage(WM_COMMAND,IDC_CUSTOMIZE,NULL);
}
Do not use SendMessage(). The button message handler must return prior to invoking the Customization dialog.
To hide and show customizable toolbars
1. Obtain a pointer to the desired toolbar. See “To obtain a pointer to a specific customizable toolbar” for more information.
2. Use the CFrameWnd::ShowControlBar() method to show or hide the toolbar.
To set the docking order of customizable toolbars
Specify the docking order via the nDockNextToID parameter of DefineDefaultToolBar. Set the value of this ID to the previous toolbar in the docking order. Here is the complete prototype for the method:
 
void SECToolBarManager::DefineDefaultToolBar(UINT nID,
const CString& strTitle,
UINT nBtnCount,
UINT* lpBtnIDs,
DWORD dwAlignment /* = CBRS_ALIGN_ANY */,
UINT nDockBarID /* = AFX_IDW_DOCKBAR_TOP */,
UINT nDockNextToID /* = NULL */,
BOOL bDocked /* = TRUE */,
BOOL bVisible /* = TRUE */)
To changing the font for text buttons
Use the static SECTBTextButton::SetTextFont() accessor method to reset the style before using the toolbar manager to create any customizable toolbars, preferably in your CMainFrame constructor. For example:
 
CMainFrame::CMainFrame()
{
CFont* pFont=LoadCustomFontFromSomewhere();
SECTBTextButton::SetTextFont(pFont);
}
To save and restore customizable toolbars
Method 1: SECWorkspaceManagerEx
Implement the SECWorkspaceManagerEx to save the state of your toolbars, docking windows, and views. For more information, see SECWorkspaceManagerEx in the Objective Toolkit Class Reference.
Method 2: LoadBarState/SaveBarState
The LoadBarState()and SaveBarState() methods are members of the SECFrameWnd and SECMDIFrameWnd frame classes. For example:
 
LoadBarState(_T("VizBarState"));
Method 3: LoadState/SaveState
The LoadState()/SaveState() methods are members of SECToolbarManager. For example:
 
pToolBarMgr->LoadState(_T("VizBarState"));
If you do not want to support toolbar persistence, you can use the SECToolBarManager::SetDockState() method directly to place default toolbars.
To draw owner-draw controls embedded in a vertically docked toolbar
In the appropriate SECWndBtn-derived class, override SetMode() and always pass FALSE through to the base implementation. For example:
 
void CMyWndBtn::SetMode(BOOL /* bVertical */)
{
SECWndBtn::SetMode(FALSE);
}
NOTE >> Take a look at the Toolbar sample located in \Samples\Toolkit\MFC\Docking\Toolbar.