运行时动态更改工具栏






4.40/5 (4投票s)
2000年8月23日

144545

2146
一个简单的教程,
动态工具栏 A 屏幕截图。
动态工具栏 B 屏幕截图。
动态工具栏 C 屏幕截图。
引言
本教程和相关的示例应用程序将教您如何在运行时动态地在三个工具栏之间切换。
我提供的示例应用程序展示了如何使用主应用程序工具栏上的 A、B 或 C 按钮在 3 个工具栏之间切换。请注意,每个动态创建的工具栏都是独立于其他工具栏的,因为它们每个都有不同的按钮 ID 和每个按钮的消息映射。
当我们希望主窗口上的工具栏不那么拥挤,但在需要时又希望拥有它们时,此方法非常有用。用户只需单击任何其他工具栏上的相关按钮即可选择他/她想要的工具栏!
此方法的另一个用途是我们需要将可以划分为单独工具栏的相关功能组合/设置在一起。例如,如果我们有一个 3D 图形应用程序,我们需要旋转、平移或缩放选定的 3D 形状。
知道在 3D 中,我们有 X、Y 和 Z 作为空间位置的参数,我们需要 3 个工具栏分别用于 3D 中的旋转、缩放和平移。通过在三个单独的工具栏上放置微调器和编辑框来修改 X、Y 和 Z 值,可以轻松更改这些参数。在这种情况下,动态工具栏会非常方便!
示例
示例 MFC 4.2 (VC++ 6 SP3) 程序演示了如何创建和使用这种动态工具栏创建方法。主工具栏上有三个 A、B 和 C 按钮来切换动态工具栏的选择。动态工具栏是 A、B 和 C,它们每个也都有四个按钮。
第一个按钮是指示哪个动态工具栏处于活动状态的指示器。其他 3 个按钮每个都将视图窗口上显示的文本及其颜色更改为另一种颜色。您可以根据需要让这些按钮执行任何其他操作,您可以编程让它们融化冰块,它们就会这样做 :)
实现方法
请按照以下步骤操作。
- 在资源编辑器中创建 3 个单独的位图,大小适合目标工具栏上的按钮数量。它们将在运行时作为工具栏按钮位图加载。将它们命名为:
IDB_BITMAP_A IDB_BITMAP_B IDB_BITMAP_C.
- 在资源头文件
Resource.h
中添加以下标记的 <<...>> 定义#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
- 在主框架的定义文件
MainFrm.h
的顶部,定义以下内容#define STYLE_A 1 // for the A toolbar #define STYLE_B 2 // for the B toolbar #define STYLE_C 3 // for the C toolbar
- 添加成员变量,如下所示
CToolBar m_wndDynTB; // Dynamic toolbar's object UINT m_nStyle; // Used for Style changing
- 在主框架的实现文件
MainFrm.cpp
中,键入以下代码//##################################################// // 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, };
- 在主框架的 OnCreate() 函数中,像这样创建初始动态工具栏
//##################################################### // 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); //#####################################################
- 为主要工具栏的 A、B 和 C 按钮以及动态工具栏的第一个按钮添加以下消息映射,以指示哪个动态工具栏处于活动状态
工具栏的第一个按钮以指示哪个动态工具栏处于活动状态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()
- 为主要工具栏的 A、B 和 C 按钮以及动态工具栏的
工具栏的第一个按钮添加以下消息处理程序,以指示哪个动态工具栏处于活动状态///////////////////////////////////////////////////////////////////////////// // 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 }
- 好的,现在我们的主框架编码已经完成,并且动态工具栏已按照上面的代码进行选择和更新,我们将更进一步,以 100% 证明此方法非常有用,尤其是在文档/视图架构中。
在文档头文件中,添加两个成员变量,分别用于文本字符串及其颜色,如下所示
COLORREF m_crTextClr; // Color for the dispalyed text CString m_strText; // The displayed text
然后在文档的构造函数中将它们初始化为任何内容,例如
m_crTextClr = RGB(255,0,0); // Default color set to Blue m_strText = _T("Masoud"); // Default text as a free poblicity! ;-)
因此,我们可以稍后通过动态工具栏按钮来更改它们作为测试!
因此,我们将像这样在 Document 类中为动态工具栏按钮添加消息映射和处理程序
在 Document 的头文件中,在
DECLARE_MESSAGE_MAP
宏的正上方手动键入这些消息处理程序// 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()
然后在 Document 的 cpp 文件中,在
END_MESSAGE_MAP
宏的正上方键入以下行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); } ////############################################# - 编译并运行该程序,如果没有意外,它应该完全正确!
最后,您可以对此方法执行任何其他操作,例如。任何单个工具栏上的更多按钮,不同的位图,正如您可能已经猜到的那样。当然,按钮背后的代码更好,可以获得更好更有用的结果。