Download source files - 34 Kb
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
A we created in the resource editor #define IDB_BITMAP_B 134
B we created in the resource editor #define IDB_BITMAP_C 133
C we created in the resource editor
the Main Toolbar >> #define ID_BUTTON_A 32776 #define ID_BUTTON_B 32777
#define ID_BUTTON_C 32778
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
#define STYLE_B 2
#define STYLE_C 3
-
Add the member variable as follows:
CToolBar m_wndDynTB;
UINT m_nStyle;
-
In the main frame's implementation file
MainFrm.cpp
, type the following codes:
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:
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;
}
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)
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)
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:
void CMainFrame::OnButtonA()
{
m_nStyle = STYLE_A;
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;
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;
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() {
enabling
the button }
void
CMainFrame::OnUpdateButtonStyleA(CCmdUI*pCmdUI) { pCmdUI->SetCheck();
an
indicator }
void
CMainFrame::OnButtonStyleB() {
the
button } void
CMainFrame::OnUpdateButtonStyleB(CCmdUI*
pCmdUI){ pCmdUI->SetCheck();
indicator
} void
CMainFrame::OnButtonStyleC()
{
button
} void CMainFrame::OnUpdateButtonStyleC(CCmdUI*
pCmdUI)
{pCmdUI->SetCheck();
}
-
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;
CString m_strText;
And then initialize them in the document's constructor to anything ie.:
m_crTextClr = RGB(255,0,0);
m_strText = _T("Masoud");
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:
protected:
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)
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.