65.9K
CodeProject 正在变化。 阅读更多。
Home

运行时动态更改工具栏

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.40/5 (4投票s)

2000年8月23日

viewsIcon

144545

downloadIcon

2146

一个简单的教程, 展示了如何在运行时动态替换工具栏

  • 下载源代码 - 34 KB
  • 动态工具栏 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 个按钮每个都将视图窗口上显示的文本及其颜色更改为另一种颜色。您可以根据需要让这些按钮执行任何其他操作,您可以编程让它们融化冰块,它们就会这样做 :)

    实现方法

    按照以下步骤操作。

    1. 在资源编辑器中创建 3 个单独的位图,大小适合目标工具栏上的按钮数量。它们将在运行时作为工具栏按钮位图加载。将它们命名为: IDB_BITMAP_A IDB_BITMAP_B IDB_BITMAP_C.

    2. 在资源头文件 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
      
    3. 在主框架的定义文件 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
      
    4. 添加成员变量,如下所示
      CToolBar 	m_wndDynTB; // Dynamic toolbar's object
      UINT	 	m_nStyle; // Used for Style changing
      
    5. 在主框架的实现文件 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,
      };
      
    6. 在主框架的 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);
      
      //#####################################################
      
    7. 为主要工具栏的 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()
      
    8. 为主要工具栏的 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
      }
      
    9. 好的,现在我们的主框架编码已经完成,并且动态工具栏已按照上面的代码进行选择和更新,我们将更进一步,以 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); } ////#############################################
    10. 编译并运行该程序,如果没有意外,它应该完全正确!

    最后,您可以对此方法执行任何其他操作,例如。任何单个工具栏上的更多按钮,不同的位图,正如您可能已经猜到的那样。当然,按钮背后的代码更好,可以获得更好更有用的结果。

    © . All rights reserved.