🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
在MS Visual Studio 2008 MFC中Ribbon界面风格出现了,这种界面风格给人带来耳目一新的感觉。Ribbon界面风格出现,可以说改革了传统的菜单式界面风格,常见的应用就是MS Office 2007中的Word、Excel、PowerPoint等组件中,Ribbon不仅使得功能有组织的存放,而且可以更加方便快捷地找到各个功能。但是MS Visual Studio 2008 MFC中还未加入Ribbon编程的相关组件,这意味着不会是那种想要什么控件就托到相应的位置就可以了,而是要完全通过代码来生成和控制相关的组件。值得然人欣喜的是,在MS Visual Studio 2010 MFC中,Ribbon编程相关的组件已经被添加了进来,这样一来Ribbon编程就变得容易了起来,可以达到“所见即所得”的效果了。 下面结合MS Visual Studio 2008 MFC中Ribbon编程的一个实例,详细讲述Ribbon编程的具体步骤和注意事项,同时还将提出一种SDI(单文档界面)架构程序中进行多个视图切换的方法。(完整的实例可在我的CSDN资源中下载:[http://download.csdn.net/detail/margin1988/6408275](http://download.csdn.net/detail/margin1988/6408275)): ⑴  MS Visual Studio 2008 MFC中创建SDIRibbon应用程序的步骤: 1)“新建”一个Visual C++ MFC应用程序项目: ![](https://box.kancloud.cn/2016-08-31_57c6b4a4c3c0b.jpg) 2)“确定”后进入MFC应用程序向导,单击“下一步”: ![](https://box.kancloud.cn/2016-08-31_57c6b4a4db700.jpg) 3)进入到应用程序类型界面,选择“单文档”、“Office”、“Office 2007(黑色主题)”,单击“下一步”: ![](https://box.kancloud.cn/2016-08-31_57c6b4a51f63a.jpg) 4)进入复合文档支持,选择“无”,单击“下一步”: ![](https://box.kancloud.cn/2016-08-31_57c6b4a55a9d0.jpg) 5)进入文档模板字符串,单击“下一步”: ![](https://box.kancloud.cn/2016-08-31_57c6b4a58eea3.jpg) 6)进入数据库支持,选择“无”,单击“下一步”: ![](https://box.kancloud.cn/2016-08-31_57c6b4a5c2bd7.jpg) 7)进入用户界面功能,按下图所示选择后,单击“下一步”: ![](https://box.kancloud.cn/2016-08-31_57c6b4a606aed.jpg) 8)进入高级功能,勾去所有的高级功能,如下图,单击“下一步”: ![](https://box.kancloud.cn/2016-08-31_57c6b4a63c47b.jpg) 9)进入生成的类,选择基类“CFormView”,单击“完成”: ![](https://box.kancloud.cn/2016-08-31_57c6b4a6955df.jpg) 10)完成后,直接编译运行程序,得到的界面如下入: ![](https://box.kancloud.cn/2016-08-31_57c6b4a6d2bcd.jpg) (2)Ribbon界面风格的主要构成分析: ![](https://box.kancloud.cn/2016-08-31_57c6b4a71c423.jpg) Ribbon应用程序的主体框架构成从大到小包含如上图中所示的三大块:分类(CMFCRibbonCategory)、面板(CMFCRibbonPanel)、元素(包括:CMFCRibbonButton、CMFCRibbonEdit等)。 (3)如何创建属于自己的Ribbon界面表现形式: 1)使用绘图、PS等工具绘制自己的按钮图标(PNG),并放在工程的res目录下,然后将其导入工程资源: ![](https://box.kancloud.cn/2016-08-31_57c6b4a79a9e6.jpg) ![](image/d41d8cd98f00b204e9800998ecf8427e.jpg) 2)在MainFrm.cpp文件的InitializeRibbon()函数中,仿照默认生成的代码编写自己的Ribbon界面表现形式,删除自动生成的你不需要的代码: A.添加资源符号: 在String Table中添加分类和面板资源符号: ![](https://box.kancloud.cn/2016-08-31_57c6b4a7b7fe9.jpg) ![](image/d41d8cd98f00b204e9800998ecf8427e.jpg) 在Accelerator中添加元素资源快捷键: ![](https://box.kancloud.cn/2016-08-31_57c6b4a7cc021.jpg) B.依次创建“分类->面板->元素”: ~~~ //创建“分类”-模块1 bNameValid = strTemp.LoadString(IDS_RIBBON_MODULAR1); ASSERT(bNameValid); CMFCRibbonCategory* pCategoryHomeMod1 = m_wndRibbonBar.AddCategory(strTemp,IDB_PNG3,IDB_PNG2,CSize(28,25),CSize(56,50)); //创建“面板”-用户管理和“元素”-按钮 bNameValid = strTemp.LoadString(IDS_RIBBON_USERMANAGER); ASSERT(bNameValid); CMFCRibbonPanel* pPanelUserManager = pCategoryHomeMod1->AddPanel(strTemp, m_PanelImages.ExtractIcon(7));//有个子图标(索引~) CMFCRibbonButton* pBtnUserManager = new CMFCRibbonButton(ID_EDIT_USERMANAGER,_T(""), 0,0);//加载的第一个(索引) pPanelUserManager->Add(pBtnUserManager); ~~~ 3)添加相应消息响应函数,使面板元素激活可用: ~~~ BEGIN_MESSAGE_MAP(CMainFrame, CFrameWndEx) ON_COMMAND(ID_EDIT_USERMANAGER, OnUserManagerCommand) ON_COMMAND(ID_EDIT_PARAMCONFIG, OnParamConfigCommand) //消息响应宏 END_MESSAGE_MAP() ~~~ 4)最终自定义的Ribbon界面表现形式如下图: ![](https://box.kancloud.cn/2016-08-31_57c6b4a7e864b.jpg) (4)SDI(单文档界面)架构想要实现多个视图之间的切换,需要定义一个切换视图的函数——void SwitchToForm(int nForm);该函数的实现体如下: ★声明全局变量**frmID:** 在stdafx.h中添加声明:extern int frmID; 在stdafx.cpp中添加定义:int frmID; 在C工程名.cpp中的InitInstance()中初始化:frmID = 0; ~~~ void CMainFrame::SwitchToForm(int nForm) {//进行视图切换的代码函数 if (nForm!=frmID) { frmID=nForm;//避免多次点击同一按钮时出现的错误,一按钮点击一次后,第二次点击不做任何处理。 CDocument* pDoc = GetActiveDocument(); CView *pOldActiveView=GetActiveView();//保存旧视图 CView *pNewActiveView=(CView*)GetDlgItem(nForm);//取得新视图 if(pNewActiveView==NULL) { switch(nForm){ case IDD_USERMANAGER_FORM ://视图资源符号 pNewActiveView=(CView*)new CPoint19View; break; case IDD_PARAMCONFIG_FORM ://视图资源符号 pNewActiveView=(CView*)new CParamConfig; break; } CCreateContext context; //将文挡和视图相连 context.m_pCurrentDoc=pOldActiveView->GetDocument(); pNewActiveView->Create(NULL, NULL, WS_BORDER|WS_CHILD, CFrameWnd::rectDefault, this, nForm, &context); pNewActiveView->OnInitialUpdate(); } SetActiveView(pNewActiveView); //改变活动的视图 pNewActiveView->ShowWindow(SW_SHOW); //显示新的视图 pOldActiveView->ShowWindow(SW_HIDE); //隐藏旧的视图 if(pOldActiveView->GetRuntimeClass() ==RUNTIME_CLASS(CPoint19View)) pOldActiveView->SetDlgCtrlID(IDD_USERMANAGER_FORM); else if(pOldActiveView->GetRuntimeClass() ==RUNTIME_CLASS(CParamConfig)) pOldActiveView->SetDlgCtrlID(IDD_PARAMCONFIG_FORM); pNewActiveView->SetDlgCtrlID(AFX_IDW_PANE_FIRST); delete pOldActiveView; //删除旧视图 RecalcLayout();//调整框架窗口 } } ~~~ 调用方式如下: ~~~ void CMainFrame::OnUserManagerCommand(){ SwitchToForm(IDD_USERMANAGER_FORM); } void CMainFrame::OnParamConfigCommand(){ SwitchToForm(IDD_PARAMCONFIG_FORM); } ~~~