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

向 MFC 功能区 (CMFCVisualManager) 添加新的主题变体

starIconstarIconstarIconstarIconstarIcon

5.00/5 (26投票s)

2017年10月31日

CPOL

3分钟阅读

viewsIcon

37512

downloadIcon

2635

为使用 VS Feature Pack 类构建的 MFC 应用程序添加新的功能区主题。

引言

本文介绍了一个派生自 CMFCVisualManager 的类,它允许在 MFC Ribbon 菜单上使用任意数量的颜色变体。 每个变体都可以简单地添加到您的应用程序的样式菜单中,并通过 CMainFrame::OnApplicationLook() 切换,就像标准主题变体一样。

我的 MFC 应用程序已经使用了 MFC Feature Pack 类和 ribbon,但我希望它具有更现代的外观,因为原始主题开始显得有些过时。 我决定看看简单地更改现有主题的颜色能做到什么程度,而不是痛苦地用付费更新的 ribbon 替换现有代码(Codejock 看起来相当不错)。 以下是我开发的类的一些可能性的示例。

Examples of what's possible with this class

文章应用程序(在 zip 下载中)重用了 Microsoft Visual Studio MFC Feature Pack 示例中的标准“RibbonGadgets”应用程序,并添加了一个“Deviant Editor”附加选项卡。 这个额外的选项卡允许您可视化设计您的新主题。 标记为“Get Code”的按钮启动一个窗口,其中包含当前主题的特定代码,您可以将其复制/粘贴到应用程序的 CMainFrame::OnApplicationLook() 中。

Sample application

单击“Get Code”按钮启动一个窗口,其中包含从示例应用程序渲染当前主题的核心 C++ 代码

Code view

Using the Code

以下说明展示了如何在新的 Visual Studio 2015 MFC 项目中实现 CMFCVisualManagerDeviant 类。 将其添加到现有项目应该非常相似。

首先,使用 Visual Studio 应用程序向导创建一个新的 MFC 应用程序,确保在“Application Type”对话框上选择“Project style”为“Office”。 在“User Interface Features”对话框上,确保选择“Use ribbon”选项。

现在,在资源编辑器中向 ribbon 的“Style”菜单添加一个新的菜单项。 在屏幕截图中,我们使用了 ID ID_VIEW_APPLOOK_DEVIANT1

Add new style to menu

现在,我们需要在 CMainFrame 中捕获 Style 菜单事件。 假设您要添加多个新样式,请导航到 CMainFrameBEGIN_MESSAGE_MAP 部分,并在 BEGIN_MESSAGE_MAP 部分中添加以下代码。 *_RANGE 宏捕获从第一个到第二个的 ID 范围。

ON_COMMAND_RANGE(ID_VIEW_APPLOOK_DEVIANT1, ID_VIEW_APPLOOK_DEVIANT1, 
                 &CMainFrame::OnApplicationLook)
ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_APPLOOK_DEVIANT1, 
ID_VIEW_APPLOOK_DEVIANT1, &CMainFrame::OnUpdateApplicationLook)

CMainFrame::OnApplicationLook() 中,进行以下更改

  1. 在以 switch (theApp.m_nAppLook) 开头的代码块中,为新的主题 ID 添加一个 case 语句,并粘贴您从示例应用程序的“Get Code”按钮选项复制的代码。 在 SetStyle() 语句中,选择与您的颜色主题最匹配的现有可视化主题枚举器 - 例如,CMFCVisualManagerOffice2007::Office2007_Silver
    case ID_VIEW_APPLOOK_DEVIANT1:
    {
                    CMFCVisualManagerOffice2007::SetStyle
                              (CMFCVisualManagerOffice2007::Office2007_Silver);
                    CMFCVisualManager::SetDefaultManager
                              (RUNTIME_CLASS(CMFCVisualManagerDeviant));
                    CMFCVisualManagerDeviant* pVisMan = 
                              (CMFCVisualManagerDeviant*)CMFCVisualManager::GetInstance();
                    if (pVisMan->GetRuntimeClass() == 
                               RUNTIME_CLASS(CMFCVisualManagerDeviant))
                    {
                        // Ribbon Bar properties
                        pVisMan->SetClrRibbonBarBackground(RGB(241, 241, 241));
                        pVisMan->SetClrRibbonBarTextPB(RGB(75, 75, 75));
                        pVisMan->SetClrRibbonBarTextHighlightedPB(RGB(0, 128, 0));
                        m_clrMenuBarBk = RGB(241, 241, 241);
    
                        // Ribbon Category Properties
                        pVisMan->SetClrRibbonCategoryBkTop(RGB(255, 255, 255));
                        pVisMan->SetClrRibbonCategoryBkBottom(RGB(255, 255, 255));
    
                        // Ribbon Panel Properties
                        pVisMan->SetClrRibbonPanelBkTop(RGB(255, 255, 255));
                        pVisMan->SetClrRibbonPanelBkBottom(RGB(255, 255, 255));
                        pVisMan->SetClrRibbonPanelCaptionBk(RGB(241, 241, 241));
                        pVisMan->SetClrRibbonPanelCaptionTextPB(RGB(68, 68, 68));
                        pVisMan->SetClrRibbonPanelCaptionTextHighlightedPB(RGB(77, 0, 38));
                        pVisMan->SetClrRibbonPanelTextPB(RGB(60, 60, 60));
    
                        // Ribbon Panel outline colour
                        pVisMan->SetClrRibbonPanelOutline(RGB(210, 210, 210));
                    }
                }
                break;
  2. CMainFrame::OnApplicationLook() 中找到以下代码行,它应该是 switch (theApp.m_nAppLook) 块中的倒数第三个语句。
       CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2007));
    将其替换为以下内容
    if(theApp.m_nAppLook >= ID_VIEW_APPLOOK_OFF_2007_BLUE && 
                 theApp.m_nAppLook <= ID_VIEW_APPLOOK_OFF_2007_AQUA)
       CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2007));
  3. 最后,在 CMainFrame::OnApplicationLook() 的开头使用 SetRedraw(FALSE) 禁用重绘,并在结尾使用 SetRedraw(TRUE) 重新启用,以避免屏幕闪烁。
  4. 这是完整的 CMainFrame::OnApplicationLook() 代码。 添加和更改都注释为以 // ** 开头

    void CMainFrame::OnApplicationLook(UINT id)
    {
       CWaitCursor wait;
    
       theApp.m_nAppLook = id;
    
       // ** Disable redrawing
       SetRedraw(FALSE);
    
       switch (theApp.m_nAppLook)
       {
       case ID_VIEW_APPLOOK_WIN_2000:
          CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManager));
          m_wndRibbonBar.SetWindows7Look(FALSE);
          break;
    
       case ID_VIEW_APPLOOK_OFF_XP:
          CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOfficeXP));
          m_wndRibbonBar.SetWindows7Look(FALSE);
          break;
    
       case ID_VIEW_APPLOOK_WIN_XP:
          CMFCVisualManagerWindows::m_b3DTabsXPTheme = TRUE;
          CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
          m_wndRibbonBar.SetWindows7Look(FALSE);
          break;
    
       case ID_VIEW_APPLOOK_OFF_2003:
          CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2003));
          CDockingManager::SetDockingMode(DT_SMART);
          m_wndRibbonBar.SetWindows7Look(FALSE);
          break;
    
       case ID_VIEW_APPLOOK_VS_2005:
          CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerVS2005));
          CDockingManager::SetDockingMode(DT_SMART);
          m_wndRibbonBar.SetWindows7Look(FALSE);
          break;
    
       case ID_VIEW_APPLOOK_VS_2008:
          CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerVS2008));
          CDockingManager::SetDockingMode(DT_SMART);
          m_wndRibbonBar.SetWindows7Look(FALSE);
          break;
    
       case ID_VIEW_APPLOOK_WINDOWS_7:
          CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows7));
          CDockingManager::SetDockingMode(DT_SMART);
          m_wndRibbonBar.SetWindows7Look(TRUE);
          break;
       default:
          switch (theApp.m_nAppLook)
          {
          case ID_VIEW_APPLOOK_OFF_2007_BLUE:
             CMFCVisualManagerOffice2007::SetStyle
                  (CMFCVisualManagerOffice2007::Office2007_LunaBlue);
             break;
    
          case ID_VIEW_APPLOOK_OFF_2007_BLACK:
             CMFCVisualManagerOffice2007::SetStyle
                 (CMFCVisualManagerOffice2007::Office2007_ObsidianBlack);
             break;
    
          case ID_VIEW_APPLOOK_OFF_2007_SILVER:
             CMFCVisualManagerOffice2007::SetStyle
                      (CMFCVisualManagerOffice2007::Office2007_Silver);
             break;
    
          case ID_VIEW_APPLOOK_OFF_2007_AQUA:
             CMFCVisualManagerOffice2007::SetStyle
                       (CMFCVisualManagerOffice2007::Office2007_Aqua);
             break;
          case ID_VIEW_APPLOOK_DEVIANT1:  // ** Use the ID you added to the 'Style' menu 
                                          // in the Ribbon editor
             {
                CMFCVisualManagerOffice2007::SetStyle
                          (CMFCVisualManagerOffice2007::Office2007_Silver);
                CMFCVisualManager::SetDefaultManager
                          (RUNTIME_CLASS(CMFCVisualManagerDeviant));
                CMFCVisualManagerDeviant* pVisMan = 
                     (CMFCVisualManagerDeviant*)CMFCVisualManager::GetInstance();
                if (pVisMan->GetRuntimeClass() == RUNTIME_CLASS(CMFCVisualManagerDeviant))
                {
                   // Ribbon Bar properties
                   pVisMan->SetClrRibbonBarBackground(RGB(0, 0, 128));
                   pVisMan->SetClrRibbonBarTextPB(RGB(255, 255, 255));
                   pVisMan->SetClrRibbonBarTextHighlightedPB(RGB(0, 0, 0));
    
                   // Ribbon Category Properties
                   pVisMan->SetClrRibbonCategoryBkTop(RGB(0, 0, 128));
                   pVisMan->SetClrRibbonCategoryBkBottom(RGB(166, 202, 240));
    
                   // Ribbon Panel Properties
                   pVisMan->SetClrRibbonPanelBkTop(RGB(166, 202, 240));
                   pVisMan->SetClrRibbonPanelBkBottom(RGB(255, 255, 255));
                   pVisMan->SetClrRibbonPanelCaptionBk(RGB(166, 202, 240));
                   pVisMan->SetClrRibbonPanelCaptionTextPB(RGB(0, 0, 128));
                   pVisMan->SetClrRibbonPanelCaptionTextHighlightedPB(RGB(255, 255, 255));
                   pVisMan->SetClrRibbonPanelTextPB(RGB(0, 0, 128));
    
                   // Ribbon Panel outline colour
                   pVisMan->SetClrRibbonPanelOutline(RGB(255, 255, 255));
                }
             }
             break;
          }
    
          // ** Set standard visual manager if it's a standard theme
          if(theApp.m_nAppLook >= ID_VIEW_APPLOOK_OFF_2007_BLUE && 
          		theApp.m_nAppLook <= ID_VIEW_APPLOOK_OFF_2007_AQUA)
             CMFCVisualManager::SetDefaultManager
                       (RUNTIME_CLASS(CMFCVisualManagerOffice2007));
    
    
          CDockingManager::SetDockingMode(DT_SMART);
          m_wndRibbonBar.SetWindows7Look(FALSE);
       }
    
       // ** Re-enable redraw
       SetRedraw(TRUE);
       RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_INVALIDATE | 
                                 RDW_UPDATENOW | RDW_FRAME | RDW_ERASE);
    
       theApp.WriteInt(_T("ApplicationLook"), theApp.m_nAppLook);
    }

您可以通过迭代上述过程来添加任意数量的其他主题。

关注点

我不打算解释 CMFCVisualManagerDeviant 类是如何工作的 - 为什么要与 Microsoft 不同,哈哈,代码就在那里供您阅读! 目标是提供一个简单的、可插入的类,可以轻松地插入到任何使用 Feature Pack ribbon 的新应用程序或现有应用程序中。 它通过几个小时的代码浏览和实验才达到现在的状态。

但是,到目前为止,有两件事一直困扰着我,我欢迎任何人贡献解决方案。

  1. 我还没有破解如何更改 Style 菜单的菜单文本颜色

    Style menu text issue

  2. 我无法更改“orb”菜单的背景颜色

    Orb menu text colour

这些问题仅在某些颜色组合上才会出现,但如果能够解决它们,那将是太棒了。

我将在收到后整合任何解决这些问题或改进此类问题的更改。

历史

  • 2017 年 10 月 31 日 - 提交初始文章
© . All rights reserved.