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





5.00/5 (26投票s)
为使用 VS Feature Pack 类构建的 MFC 应用程序添加新的功能区主题。
引言
本文介绍了一个派生自 CMFCVisualManager
的类,它允许在 MFC Ribbon 菜单上使用任意数量的颜色变体。 每个变体都可以简单地添加到您的应用程序的样式菜单中,并通过 CMainFrame::OnApplicationLook()
切换,就像标准主题变体一样。
我的 MFC 应用程序已经使用了 MFC Feature Pack 类和 ribbon,但我希望它具有更现代的外观,因为原始主题开始显得有些过时。 我决定看看简单地更改现有主题的颜色能做到什么程度,而不是痛苦地用付费更新的 ribbon 替换现有代码(Codejock 看起来相当不错)。 以下是我开发的类的一些可能性的示例。
文章应用程序(在 zip 下载中)重用了 Microsoft Visual Studio MFC Feature Pack 示例中的标准“RibbonGadgets
”应用程序,并添加了一个“Deviant Editor”附加选项卡。 这个额外的选项卡允许您可视化设计您的新主题。 标记为“Get Code”的按钮启动一个窗口,其中包含当前主题的特定代码,您可以将其复制/粘贴到应用程序的 CMainFrame::OnApplicationLook()
中。
单击“Get Code”按钮启动一个窗口,其中包含从示例应用程序渲染当前主题的核心 C++ 代码
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
。
现在,我们需要在 CMainFrame
中捕获 Style 菜单事件。 假设您要添加多个新样式,请导航到 CMainFrame
的 BEGIN_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()
中,进行以下更改
- 在以
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;
- 在
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));
- 最后,在
CMainFrame::OnApplicationLook()
的开头使用SetRedraw(FALSE)
禁用重绘,并在结尾使用SetRedraw(TRUE)
重新启用,以避免屏幕闪烁。 -
这是完整的
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 的新应用程序或现有应用程序中。 它通过几个小时的代码浏览和实验才达到现在的状态。
但是,到目前为止,有两件事一直困扰着我,我欢迎任何人贡献解决方案。
- 我还没有破解如何更改 Style 菜单的菜单文本颜色
- 我无法更改“
orb
”菜单的背景颜色
这些问题仅在某些颜色组合上才会出现,但如果能够解决它们,那将是太棒了。
我将在收到后整合任何解决这些问题或改进此类问题的更改。
历史
- 2017 年 10 月 31 日 - 提交初始文章