Changing toolbars dynamically at runtime






4.40/5 (4 votes)
Aug 23, 2000

143749

2146
A simple tutorial that shows how to dynamically replace toolbars at runtime
Dynamic Toolbar A screen shot.
Dynamic Toolbar B screen shot.
Dynamic Toolbar C screen shot.
Introduction
This tutorial and the associated sample application will teach you how to dynamically swap between three toolbars at runtime.
The sample application I've provided shows how it is possible to toggle between the 3 toolbars by using the A, B or C buttons that are on the Main Application Toolbar. Please note that each of these dynamically created toolbars function separately from each, since they each have different button IDs and Message Maps of each button.
This method can be very useful when we need to have less of a crowd of toolbars on the main window but at the same time have them when you need them. It is up to the user to select what toolbar He/She wants by simply clicking the related button on any other toolbar!
Another use for this method is when we need to group/set together the related functions that can be devided into separate toolbars. For example if we have a 3D Graphic Application, We would need to Rotate, Translate or Scale the selected 3D shape.
Knowing that in 3D we have X, Y and Z as parameters for position in space, we would need 3 Toolbars for each of Rotation, Scaling and Translation in 3D. These parameters can easily be changed by having three separate toolbars with Spinners and Edit boxes on them to modify the X, Y & Z values. The Dynamic Toolbars will come very handy in this case!
Sample:
The sample MFC 4.2 ( VC++ 6 SP3 ) program demontrates how to create and use this method of dynamic toolbar creation. The main toobar has three A, B and C buttons on them to toggle dynamic toolbar selection. The dynamic toolbars are A, B and C that also each have four buttons on them.
The first button is an indicator for which dynamic toolbar is active. The other 3 buttons each change the displayed text and its color on the view window to another color. It can be any thing else as you wish for these buttons to do, you program them to melt ice and they will :)
How it is done:
F ollow the steps below.
-
Create 3 separate Bitmaps in the resource editor with the size to fit the number of buttons on
the target toolbar. They will be loaded as the toolbar button bitmaps later at runtime.
Name them as:
IDB_BITMAP_A IDB_BITMAP_B IDB_BITMAP_C.
-
Add the following marked <<...>> defines in the resource header
Resource.h
file:#define IDB_BITMAP_A 132 // The bitmap for toolbar A we created in the resource editor #define IDB_BITMAP_B 134 // The bitmap for toolbar B we created in the resource editor #define IDB_BITMAP_C 133 // The bitmap for toolbar C we created in the resource editor // << Buttons A, B & C on the Main Toolbar >> #define ID_BUTTON_A 32776 #define ID_BUTTON_B 32777 #define ID_BUTTON_C 32778 // << Styles and Buttons of the Dynamic Toolbar A >> #define ID_BUTTON_STYLE_A 34500 #define ID_BUTTON_A_ONE 34501 #define ID_BUTTON_A_TWO 34502 #define ID_BUTTON_A_THREE 34503 // << Styles and Buttons of the Dynamic Toolbar B >> #define ID_BUTTON_STYLE_B 34504 #define ID_BUTTON_B_ONE 34505 #define ID_BUTTON_B_TWO 34506 #define ID_BUTTON_B_THREE 34507 // << Styles and Buttons of the Dynamic Toolbar C >> #define ID_BUTTON_STYLE_C 34508 #define ID_BUTTON_C_ONE 34509 #define ID_BUTTON_C_TWO 34510 #define ID_BUTTON_C_THREE 34511
-
At the top of main frame's definition file
MainFrm.h
, define the followings:#define STYLE_A 1 // for the A toolbar #define STYLE_B 2 // for the B toolbar #define STYLE_C 3 // for the C toolbar
-
Add the member variable as follows:
CToolBar m_wndDynTB; // Dynamic toolbar's object UINT m_nStyle; // Used for Style changing
-
In the main frame's implementation file
MainFrm.cpp
, type the following codes://##################################################// // Dynamic Toolbar button definitions array and IDs static UINT BASED_CODE ToolsA[] = { ID_BUTTON_STYLE_A, ID_SEPARATOR, ID_BUTTON_A_ONE, ID_BUTTON_A_TWO, ID_BUTTON_A_THREE, }; static UINT BASED_CODE ToolsB[] = { ID_BUTTON_STYLE_B, ID_SEPARATOR, ID_BUTTON_B_ONE, ID_BUTTON_B_TWO, ID_BUTTON_B_THREE, }; static UINT BASED_CODE ToolsC[] = { ID_BUTTON_STYLE_C, ID_SEPARATOR, ID_BUTTON_C_ONE, ID_BUTTON_C_TWO, ID_BUTTON_C_THREE, };
-
Create the initial dynamic toolbar like this in the main frame's OnCreate() function:
//##################################################### // Dynamic Toolbar Creation if (!m_wndDynTB.CreateEx(this, TBSTYLE_FLAT , WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_wndDynTB.LoadBitmap(IDB_BITMAP_A) || !m_wndDynTB.SetButtons(ToolsA, sizeof(ToolsA)/sizeof(UINT))) { TRACE0("Failed to create the light toolbar.\n"); return -1; // if failed to create } //##################################################### // Add thiese to the end of create function m_wndDynTB.EnableDocking(CBRS_ALIGN_ANY); m_wndDynTB.SetWindowText(_T("Dynamic Toolbar Style A")); DockControlBar(&m_wndDynTB); //#####################################################
-
Add the following message maps for the buttons A, B & C of the Main Toolbar and the Dynamic
toolbars' First Buttons to indicate what Dynamic Toolbar is Active:BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) //{{AFX_MSG_MAP(CMainFrame) ON_WM_CREATE() ON_COMMAND(ID_BUTTON_A, OnButtonA) ON_COMMAND(ID_BUTTON_B, OnButtonB) ON_COMMAND(ID_BUTTON_C, OnButtonC) ON_UPDATE_COMMAND_UI(ID_BUTTON_A, OnUpdateButtonA) ON_UPDATE_COMMAND_UI(ID_BUTTON_B, OnUpdateButtonB) ON_UPDATE_COMMAND_UI(ID_BUTTON_C, OnUpdateButtonC) //}}AFX_MSG_MAP // Dynamic Toolbar <u>First Buttons</U> Message Maps ON_COMMAND(ID_BUTTON_STYLE_A , OnButtonStyleA) ON_UPDATE_COMMAND_UI(ID_BUTTON_STYLE_A, OnUpdateButtonStyleA) ON_COMMAND(ID_BUTTON_STYLE_B , OnButtonStyleB) ON_UPDATE_COMMAND_UI(ID_BUTTON_STYLE_B, OnUpdateButtonStyleB) ON_COMMAND(ID_BUTTON_STYLE_C , OnButtonStyleC) ON_UPDATE_COMMAND_UI(ID_BUTTON_STYLE_C, OnUpdateButtonStyleC) END_MESSAGE_MAP()
-
Add the following message handlers for the buttons A, B & C of the Main Toolbar and the Dynamic
toolbars' First Buttons to indicate what Dynamic Toolbar is Active:///////////////////////////////////////////////////////////////////////////// // CMainFrame message handlers void CMainFrame::OnButtonA() { m_nStyle = STYLE_A;//1; Invalidate(); m_wndDynTB.SetButtons(ToolsA, sizeof(ToolsA)/sizeof(UINT)); m_wndDynTB.LoadBitmap(IDB_BITMAP_A); m_wndDynTB.SetWindowText(_T("Dynamic Toolbar Style A")); m_wndDynTB.InvalidateRect(NULL,TRUE); } void CMainFrame::OnButtonB() { m_nStyle = STYLE_B;//2; Invalidate(); m_wndDynTB.SetButtons(ToolsB, sizeof(ToolsB)/sizeof(UINT)); m_wndDynTB.SetWindowText(_T("Dynamic Toolbar Style B")); m_wndDynTB.LoadBitmap(IDB_BITMAP_B); m_wndDynTB.InvalidateRect(NULL,TRUE); } void CMainFrame::OnButtonC() { m_nStyle = STYLE_C;//3; Invalidate(); m_wndDynTB.SetButtons(ToolsC, sizeof(ToolsC)/sizeof(UINT)); m_wndDynTB.SetWindowText(_T("Dynamic Toolbar Style C")); m_wndDynTB.LoadBitmap(IDB_BITMAP_C); m_wndDynTB.InvalidateRect(NULL ,TRUE); } void CMainFrame::OnUpdateButtonA(CCmdUI* pCmdUI) {pCmdUI->SetCheck(m_nStyle == STYLE_A); } void CMainFrame::OnUpdateButtonB(CCmdUI* pCmdUI) {pCmdUI->SetCheck(m_nStyle == STYLE_B); } void CMainFrame::OnUpdateButtonC(CCmdUI* pCmdUI) {pCmdUI->SetCheck(m_nStyle == STYLE_C); } void CMainFrame::OnButtonStyleA() { // Keep here Empty, just for enabling the button } void CMainFrame::OnUpdateButtonStyleA(CCmdUI*pCmdUI) { pCmdUI->SetCheck();// Used to always check this first button as an indicator } void CMainFrame::OnButtonStyleB() { // Keep here Empty, just for enabling the button } void CMainFrame::OnUpdateButtonStyleB(CCmdUI* pCmdUI){ pCmdUI->SetCheck();// Used to always check this first button as an indicator } void CMainFrame::OnButtonStyleC() { // Keep here Empty, just for enabling the button } void CMainFrame::OnUpdateButtonStyleC(CCmdUI* pCmdUI) {pCmdUI->SetCheck(); // Used to always check this first button as an indicator }
-
O.K., Now that our main frame coding is done and the Dynamic Toolbars are selected and updated as the
codes above make them do, we will go a little further to prove 100% that this method is very
useful especially in the document/view architecture.
In the document header, add two member variables for text string and it's color like this:
COLORREF m_crTextClr; // Color for the dispalyed text CString m_strText; // The displayed text
And then initialize them in the document's constructor to anything ie.:
m_crTextClr = RGB(255,0,0); // Default color set to Blue m_strText = _T("Masoud"); // Default text as a free poblicity! ;-)
So we can change them later by the dynamic toolbar buttons as a test!
We therefore are going to add the message maps and handlres for the Dynamic Toolbar buttons inside the Document class like this:
Type these message handlres by hand In the Document's header file just above the
DECLARE_MESSAGE_MAP
macro:// Generated message map functions protected: //{{AFX_MSG(CDynamicTBDoc) //}}AFX_MSG // My Dynamic Toolbar messgae maps afx_msg void OnButtonAOne(); afx_msg void OnButtonATwo(); afx_msg void OnButtonAThree(); afx_msg void OnButtonBOne(); afx_msg void OnButtonBTwo(); afx_msg void OnButtonBThree(); afx_msg void OnButtonCOne(); afx_msg void OnButtonCTwo(); afx_msg void OnButtonCThree(); DECLARE_MESSAGE_MAP()
And in the Document's cpp file type the following lines just above the
END_MESSAGE_MAP
macro:BEGIN_MESSAGE_MAP(CDynamicTBDoc, CDocument) //{{AFX_MSG_MAP(CDynamicTBDoc) //}}AFX_MSG_MAP ////############################################# ON_COMMAND(ID_BUTTON_A_ONE , OnButtonAOne) ON_COMMAND(ID_BUTTON_A_TWO , OnButtonATwo) ON_COMMAND(ID_BUTTON_A_THREE , OnButtonAThree) ON_COMMAND(ID_BUTTON_B_ONE , OnButtonBOne) ON_COMMAND(ID_BUTTON_B_TWO , OnButtonBTwo) ON_COMMAND(ID_BUTTON_B_THREE , OnButtonBThree) ON_COMMAND(ID_BUTTON_C_ONE , OnButtonCOne) ON_COMMAND(ID_BUTTON_C_TWO , OnButtonCTwo) ON_COMMAND(ID_BUTTON_C_THREE , OnButtonCThree) ////############################################# END_MESSAGE_MAP()
And in the Document's cpp file then type the following functions for message handlers we declared above:
////############# Toolbar A #################### void CDynamicTBDoc::OnButtonAOne() { m_crTextClr = RGB(0,255,0); m_strText = _T("Samimi"); SetModifiedFlag(); UpdateAllViews(NULL); } void CDynamicTBDoc::OnButtonATwo() { m_crTextClr = RGB(0,255,255); m_strText = _T("Test"); SetModifiedFlag(); UpdateAllViews(NULL); } void CDynamicTBDoc::OnButtonAThree() { m_crTextClr = RGB(255,105,0); m_strText = _T("For"); SetModifiedFlag(); UpdateAllViews(NULL); } ////############# Toolbar B #################### void CDynamicTBDoc::OnButtonBOne() { m_crTextClr = RGB(128,255,128); m_strText = _T("Dynamic"); SetModifiedFlag(); UpdateAllViews(NULL); } void CDynamicTBDoc::OnButtonBTwo() { m_crTextClr = RGB(0,128,128); m_strText = _T("Toolbar"); SetModifiedFlag(); UpdateAllViews(NULL); } void CDynamicTBDoc::OnButtonBThree() { m_crTextClr = RGB(128,20,0); m_strText = _T("And"); SetModifiedFlag(); UpdateAllViews(NULL); } ////############# Toolbar C #################### void CDynamicTBDoc::OnButtonCOne() { m_crTextClr = RGB(0,255,0); m_strText = _T("IT"); SetModifiedFlag(); UpdateAllViews(NULL); } void CDynamicTBDoc::OnButtonCTwo() { m_crTextClr = RGB(0,255,0); m_strText = _T("FULLY"); SetModifiedFlag(); UpdateAllViews(NULL); } void CDynamicTBDoc::OnButtonCThree() { m_crTextClr = RGB(0,255,0); m_strText = _T("WORKSSS!!!"); SetModifiedFlag(); UpdateAllViews(NULL); } ////############################################# - Compile and run the program and without surprises it should be completamenete allright!
And finally, you can do anything else as you wish with this method ie. More buttons on any single toolbar, different bitmaps as you may have guessed already. And of course better code behind the buttons for much better and useful results.