2023年12月22日发(作者:)

Visual Studio 2010系列之 创建华丽Ribbon界面(上)

随着Office 2007的发布,它改变了以往传统的下拉式菜单用户界面,取而代之的是全新的被称之为“Ribbon”的固定式工具栏界面。微软声称这种新的用户界面能够使用户更容易地使用软件的各项常用功能,例如Word 2007中的保存,设置格式,插入图片等常用功能,都可以从Ribbon界面快速地访问到,从而提高用户的生产效率。 虽然很多用户还在抱怨“不习惯Ribbon界面”、“很多功能找不到位置”等等,但是,随着微软的“强制”推行,Ribbon界面也在越来越被人们所接受,很多应用软件也开始采用Ribbon界面。更重要的是,在即将到来的Windows 7中,操作系统本身更是大量地应用了Ribbon界面。不管我们愿意或者不愿意,Ribbon界面开始大张旗鼓地攻占我们的软件界面,成为继下拉式菜单后新的标准用户界面。作为用户,我们需要逐渐熟悉这种新的软件用户界面;而作为开发者,更是需要了解和认识这种新的软件用户界面,新的交互方式,从而利于这种新界面的优势,为用户提供更加优秀的软件。

“Ribbon来了!”

Windows平台的进化,往往都伴随着系统图形界面的重新设计。从Windows XP到Windows

Vista,最大的革新就是Windows Aero的引入。而在微软的下一代Windows平台Windows

7中,虽然Aero被保留下来,但是Windows 7的图形用户界面更多的是朝着Office 2007相同的方向前进,无论是系统自带的工具软件,例如画图、写字板等,还是上层的第三方应用软件,例如Office 2007、AutoCAD、SnagIt等等,都全面应用了Ribbon界面。

图1 Windows 7中随处可见的Ribbon界面

在传统的软件界面设计中,我们都是采用“文件”、“编辑”、“视图”的菜单模式,这俨然成为软件界面设计的标准。但是现实的情况是,随着软件的功能越来越强大,下拉菜单也随之变得越来越长,用户根本不清楚菜单深处到底隐藏着什么重要的功能。这往往意味着用户要求软件实现的功能,其实软件早已经具有了,只是在菜单中隐藏得比较深,用户没有找到而已。越来越长的菜单的另外一个弊端是,很多常用的功能被埋没在众多的菜单项中,使得用户在使用常用的功能时,还需要进行多次菜单选择,这无疑降低了工作效率。为了改变这种现状,微软进行了大量的研究,在广泛听取用户意见的基础上,同时经过了严格的可用性测试,终于在Office 2007中推出了革命性的Ribbon界面。

跟传统的菜单式用户界面相比较,Ribbon界面的优势主要体现在如下几个方面:

• 所有功能有组织地集中存放,不再需要查找级联菜单、工具栏等等

• 更好地在每个应用程序中组织命令

• 提供足够显示更多命令的空间

• 丰富的命令布局可以帮助用户更容易地找到重要的,常用的功能

• 可以显示图示,对命令的效果进行预览,例如改变文本的格式等

• 更加适合触摸屏操作

虽然从菜单式界面到Ribbon界面有一个漫长的熟悉的过程,但是一个不争的事实是,Ribbon界面正在被越来越多的人接受,相应的,越来越多的软件开发商开始抛弃传统的菜单式界面,转而采用Ribbon界面。Visual Studio 2010作为面向下一代Windows平台的开发工具,自然是对Ribbon界面全面支持。下面我们就来看看如何利于Visual Studio

2010开发面向Windows 7的Ribbon界面。

创建MFC应用程序项目

实际上,Ribbon界面(Office 2007风格的界面)的开发早在2008年就随着Visual C++

Feature Pack被引入到Visual Studio 2008中。在即将到来的Visual Studio 2010中,Ribbon界面的开发更是得到了原生的支持,使得Ribbon界面的开发更加简便高效。

首先,我们启动Visual Studio 2010,创建一个基于MFC的应用程序,项目模板我们选择“MFC Application”:

图2 创建MFC应用程序

在接下来的“MFC应用程序向导”中,我们就可以对项目的可视化风格进行选择和配置。Visual Studio 2010支持MFC风格、标准的Windows风格,Visual Studio 2005风格和Office 2007风格。而这里的Office 2007风格,就是我们要创建的Ribbon界面:

图3 设置Ribbon界面风格

在接下来的向导页中,我们可以选择命令栏(工具栏。菜单栏)的样式,这里我们当然选择“Use a ribbon”了。当然,为了跟旧有的系统保持兼容,Visual Studio 2010也支持传统的命令式界面,如果你的用户比较保守,想继续使用传统的菜单式界面,我们可以选择“Use a menu bar and toolbar”:

图4 选择命令栏的风格

为了支持丰富的Office 2007界面风格,MFC默认情况下为MFC文档应用程序添加了类似Outlook风格的导航面板(Navigation pane)和标题条(Caption bar)。这两者并不是我们关注的重点,为了更好的展示Ribbon界面,我们这里就去掉这两个多余的面板:

图5 去掉多余的界面元素

到这里,针对新项目的设置就完成了,点击“Finish”按钮关闭应用程序向导,Visual

Studio 2010就会按照我们的设置创建相应的MFC应用程序解决方案。编译运行这个解决方案,我们就得到了第一个具有Ribbon界面的应用程序。

图6 第一个Ribbon界面应用程序

Ribbon界面的构成

为了支持新的界面风格的开发,MFC提供了很多新的、经过扩展过后的应用程序类,界面类等。例如在我们的实例程序中用到的CRibbonApp,CMainFrame就是分别从CWinAppEx,CMDIFrameWndEx派生的。而CWinAppEx和CMDIFrameWndEx又是从传统的CWinApp和CMDIFrameWnd派生,在原有类的基础上,添加了对新的界面风格的支持。

图7 支持新的界面风格的框架类

熟悉MFC界面开发的朋友都知道,应用程序的CMainFrame类负责整个主框架界面的创建和管理,在传统的菜单式界面下,它负责创建和管理菜单栏,状态栏,工具栏等。同样的,在Ribbon界面下,它同样负责Ribbon界面的创建和管理。

class CMainFrame : public CMDIFrameWndEx

{

DECLARE_DYNAMIC(CMainFrame)public:

CMainFrame();// Attributespublic:// Operationspublic:// Overridespublic:

virtual BOOL PreCreateWindow(CREATESTRUCT& cs);// Implementationpublic:

virtual ~CMainFrame();

#ifdef _DEBUG virtual void AssertValid() const; virtual void

Dump(CDumpContext& dc) const;#endifprotected: // control bar embedded members

CMFCRibbonBar m_wndRibbonBar;

CMFCRibbonApplicationButton m_MainButton;

CMFCToolBarImages m_PanelImages;

CMFCRibbonStatusBar m_wndStatusBar;// Generated message map

functionsprotected:

afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

afx_msg void OnWindowManager();

afx_msg void OnApplicationLook(UINT id);

afx_msg void OnUpdateApplicationLook(CCmdUI* pCmdUI);

DECLARE_MESSAGE_MAP() void InitializeRibbon();

};

从上面的代码中我们可以看到,在Ribbon界面下,CMainFrame类包含了三个成员变量:m_wndRibbonBar、m_MainButton、m_wndStatusBar,分别用于控制Ribbon界面的命令面板,应用程序按钮和状态栏。清楚了各个变量对应的Ribbon界面元素后,我们就可以操作相应的成员变量,在Ribbon界面上添加我们需要的内容。

图8 Ribbon界面的构成

处理菜单资源和消息响应函数

Ribbon界面相对于传统的菜单式界面,最大的差别就是用新的Ribbon Bar代替了传统的菜单栏。我们可以看到,在默认情况下,Ribbon Bar已经拥有了一个名为“Home”的命令分组(Category),其中又包含了多个面板(Panel),每个面板中有一个或者多个命令按钮(Ribbon Button)。下面我们就来看看如何在Ribbon Bar上添加一个新的命令分组,然后在其中添加新的命令按钮以执行相应的功能。

按照传统的菜单式界面的开发流程,我们总是先编辑菜单资源,然后再创建相应的菜单命令消息响应函数,最后再实现这个消息响应函数,完成相应的任务。在新的Ribbon界面中,我们还是先要按照这样的流程,完成菜单资源的编辑,实现消息响应函数等。所以,我们先打开Visual Studio 2010的资源编辑器,在IDR_RibbonUITYPE菜单资源中添加两个新的菜单项。

图9 编辑菜单资源

然后,我们分别为这两个菜单项添加相应的消息响应函数:

图10 添加消息响应函数

这里,我们只是演示Ribbon界面的创建,所以我们将这两个消息响应函数简单地实现如下:

// CRibbonUIView message handlersvoid CRibbonUIView::OnEditSayhello()

{ // TODO: Add your command handler code here AfxMessageBox(_T("Hello

RibbonUI!"));

}void CRibbonUIView::OnEditSaygoodbye()

{ // TODO: Add your command handler code here AfxMessageBox(_T("Goodbye

RibbonUI!"));

}

添加Ribbon按钮 到现在为止,我们已经按照菜单式界面的开发流程,完成了资源的编辑和消息函数的实现。如果这时我们编译运行解决方案,我们在程序界面上看不到任何变化,因为我们还没有把这些命令绑定到Ribbon Bar的命令按钮上。在CMainFrame类中,它提供了一个专门的函数CMainFrame::InitializeRibbon()来完成Ribbon界面的初始化工作,所以,我们在这个函数中添加如下代码,创建新的命令分组,然后将命令按钮映射到我们刚刚创建的菜单项。

void CMainFrame::InitializeRibbon()

{

BOOL bNameValid;

///„

//////////////////////////////////////////////////////////////

// 添加一个命令分组(Category)“RibbonUI Category” CMFCRibbonCategory

*pRibbonUICategory =

m_egory(_T("RibbonUI Category"),

IDB_WRITESMALL, IDB_WRITELARGE);

// 添加一个面板(Panel) CMFCRibbonPanel *pTestPanel =

pRibbonUICategory->AddPanel(_T("RibbonUI Panel"), m_tIcon(1));

// 在面板上添加Ribbon命令按钮(CMFCRibbonButton)

pTestPanel->Add(new CMFCRibbonButton(ID_EDIT_SAYHELLO, _T("Say Hello"), 0, 0));

pTestPanel->Add(new CMFCRibbonButton(ID_EDIT_SAYHELLO, _T("Say Hello"), 1));

pTestPanel->Add(new CMFCRibbonButton(ID_EDIT_SAYGOODBYE, _T("Say Goodbye"),

2));

//////////////////////////////////////////////////////////////

///„ }

在这段代码中,我们首先利用Ribbon Bar的AddCategory()函数,添加了一个新的命令分组(Category),也就是Ribbon Bar上的一个新的标签页。然后,我们在这个新创建的标签页中,添加了一个新的面板(Panel)。最后,我们创建了三个Ribbon命令按钮(CMFCRibbonButton),并将它们放置到面板中。通过指定跟菜单资源中的菜单项相同的资源ID,我们将这些Ribbon命令按钮跟我们之前创建的菜单项一一对应起来。当我们点击某个Ribbon命令按钮时,就会执行相应的菜单命令响应函数。这样,我们就实现了菜单命令在Ribbon Bar的绑定,同时在界面上也能看到我们刚刚添加的命令按钮了。

图11 新创建的命令按钮

在这里,我们只是简单地向大家介绍了Ribbon界面的基本概念和大致的开发流程,要想开发跟Office 2007一样专业的Ribbon界面,我们还有很长的一段路要走,敬请关注本系列文章,创建面向Windows 7的用户界面。

Visual Studio 2010系列之 创建华丽Ribbon界面(下)

上回我们介绍了Windows 7中对Ribbon界面的广泛应用,随着今天Windows 7 Beta1的公开测试,我们也逐渐感觉到Ribbon界面离我们越来越近了。作为程序员,我们做好了迎接Ribbon界面的准备了吗?

在上回中,我们简单地介绍了开发Ribbon界面的一般流程,同时演示了如何创建包含命令按钮(CMFCRibbonButton)的简单Ribbon界面,相信很多朋友都跃跃欲试,想为自己的软件创建专业的Ribbon界面。但是,仅仅使用命令按钮是远远不能满足软件界面的交互需求的,同时也没有完全发挥Ribbon界面的强大威力。为了支持Ribbon界面,Visual

Studio 2010为我们提供了很多控件,除了我们上回介绍的命令按钮(CMFCRibbonButton)之外,还有工具廊(CMFCRibbonGallery),颜色按钮(CMFCRibbonColorButton),编辑框(CMFCRibbonEdit),进度条(CMFCRibbonProgressBar)等等。合理地使用这些控件,我们可以创建丰富的Ribbon界面,增强软件的可用性。在这回中,我们就介绍一下如何使用这些控件,创建更加复杂的Ribbon界面,完成更加复杂的交互任务。

为了更好地理解和创建Ribbon界面,在开始具体地介绍各种控件之前,我们先来了解一下Ribbon界面的结构层次。在上一回中,我们介绍了Ribbon界面主要由Ribbon面板(CMFCRibbonBar)构成,而Ribbon面板主要的主要分为三个层次:

• 分类(CMFCRibbonCategory)

图1 分类

很明显,“分类”就是作用相近的一类命令的组合。例如在Word 2007的Ribbon界面中,微软将跟插入元素相关的命令都放在“Insert”这个页面中,当用户想在Word文档中插入其他元素时,只要切换到这一页就可以找到他需要的命令。在形式上,“分类”表现为Ribbon面板上的一个Tab页面。我们可以使用函数AddCategory()在Ribbon面板上添加一个新的“分类”:

// 添加一个命令分组(Category)“RibbonUI Category”CMFCRibbonCategory

*pRibbonUICategory =

m_egory(_T("RibbonUI

Category"),

IDB_WRITESMALL, IDB_WRITELARGE);

• 面板(CMFCRibbonPanel)

图2 面板

“面板”是“分类”的下一个层次。它是联系更加紧密的一组命令的组合。面板总是被放置在某个“分类”中,被“分类”所包含。同时,“面板”又是一个容器,它包含着它的下一个层次“元素”。我们可以通过AddPanel()函数在“分类”中添加新的“面板”:

// 添加一个面板(Panel)CMFCRibbonPanel *pTestPanel =

pRibbonUICategory->AddPanel(_T("RibbonUI Panel"),

m_tIcon(1));

• 元素(CMFCRibbonBaseElement)

图3 元素

“元素”就是我们通常意义上的控件、这些控件根据各自的功能,被分组放置在各个“面板”上,负责完成具体的交互任务。Visual Studio 2010提供的Ribbon界面“元素”主要包括命令按钮(CMFCRibbonButton)。工具廊(CMFCRibbonGallery)、颜色按钮(CMFCRibbonColorButton)、编辑框(CMFCRibbonEdit)、进度条(CMFCRibbonProgressBar)等等。这些类都派生自CMFCRibbonBaseElement。

图4 丰富的Ribbon控件

下面我们就来详细介绍各种Ribbon控件的使用。

命令按钮

命令按钮可以说是我们最常用的Ribbon控件了,我们通常都是通过命令按钮来发送某个命令,执行某个动作。它代替了过去的菜单命令,成为使用最频繁的Ribbon控件。在Ribbon界面中,主要有三种形式的命令按钮:大图标按钮,小图标按钮以及表示选择的复选按钮(CheckBox)。

图5 命令按钮

按照上回我们介绍的Ribbon界面开发流程,我们需要先准备菜单资源,图标资源,实现消息响应函数等,这里我们就不再赘述这一过程,而把重点放在如何创建Ribbon界面。下面的代码分别演示了这三种按钮的创建过程:

// 创建一个新的面板,用于放置大图标按钮CMFCRibbonPanel* pPanel1 =

pCategory->AddPanel(_T("Large Buttons"));// 创建按钮CMFCRibbonButton* pBtn1 =

new CMFCRibbonButton(ID_RIBBON_BTN_1, _T("Button"), 0, 0);// 指定使用大图标pBtn1->SetAlwaysLargeImage();// 将按钮添加到面板中pPanel1->Add(pBtn1);

CMFCRibbonButton* pBtn2 = new CMFCRibbonButton(ID_RIBBON_BTN_2, _T("Menu Button"),

1, 1);// 可以通过SetMenu()函数为按钮设置一个子菜单

pBtn2->SetMenu(IDR_RIBBON_MENU_1);

pBtn2->SetAlwaysLargeImage();

pPanel1->Add(pBtn2);

CMFCRibbonButton* pBtn3 = new CMFCRibbonButton(ID_RIBBON_BTN_3, _T("Split

Button"), 2, 2);

pBtn3->SetMenu(IDR_RIBBON_MENU_1, TRUE);

pBtn3->SetAlwaysLargeImage();// 可以通过RemoveSubItem()和AddSubItem()动态地改变按钮的子项目pBtn3->RemoveSubItem(0);

pBtn3->AddSubItem(new CMFCRibbonButton(ID_RIBBON_MBTN_1, _T("Item 1"), 2), 0);

pPanel1->Add(pBtn3);// 创建新的面板,用于放置小图标按钮CMFCRibbonPanel* pPanel2

= pCategory->AddPanel(_T("Small"));// 创建小图标按钮CMFCRibbonButton* pBtn4 =

new CMFCRibbonButton(ID_RIBBON_BTN_4, _T("Button"), 3);

pPanel2->Add(pBtn4);

CMFCRibbonButton* pBtn5 = new CMFCRibbonButton(ID_RIBBON_BTN_5, _T("Menu Button"),

4);

pBtn5->SetMenu(IDR_RIBBON_MENU_1);

pPanel2->Add(pBtn5);

CMFCRibbonButton* pBtn6 = new CMFCRibbonButton(ID_RIBBON_BTN_6, _T("Split

Button"), 5);

pBtn6->SetMenu(IDR_RIBBON_MENU_1, TRUE);

pBtn6->SetAlwaysLargeImage();

pBtn6->RemoveSubItem(1);

pBtn6->AddSubItem(new CMFCRibbonButton(ID_RIBBON_MBTN_2, _T("Item 2"), 5), 1);

pPanel2->Add(pBtn6);//创建新的面板,用于放置复选按钮CMFCRibbonPanel* pPanel3 =

pCategory->AddPanel(_T("Check Boxes"));

pPanel3->Add(new CMFCRibbonCheckBox(ID_RIBBON_BTN_7, _T("Check Box 1")));

pPanel3->Add(new CMFCRibbonCheckBox(ID_RIBBON_BTN_8, _T("Check Box 2")));

pPanel3->Add(new CMFCRibbonCheckBox(ID_RIBBON_BTN_9, _T("Check Box 3")));

工具廊

Ribbon界面的一个重要革新,就是可以通过工具廊(CMFCRibbonGallery)控件,对命令的执行效果进行直观地预览。例如Word 2007的段落格式设置,就是通过工具廊直观地展示了格式的样子,这很大程度上减少了用户通过不断尝试各种参数找到合适格式的过程。

图6 工具廊

下面我们就来看看如何创建工具廊这种新的交互工具。如下的代码,演示了工具廊控件的创建过程:

CMFCRibbonPanel* pPanel1 = pCategory->AddPanel(_T("Standard"));// 创建一个标准的工具廊控件,其中IDB_RIBBON_PALETTE_1指定了// 工具廊中的各个按钮的图标,通过这些图标对命令效果进行预览pPanel1->Add(new CMFCRibbonGallery(ID_RIBBON_PBTN_1,

_T("Embedded"), 0, 0, IDB_RIBBON_PALETTE_1, 64));// 按钮模式的工具廊控件// 按钮模式的工具廊控件可以减少对面板空间的占用CMFCRibbonGallery* pBtn2 = new

CMFCRibbonGallery(ID_RIBBON_PBTN_2, _T("Button"), 1, 1, IDB_RIBBON_PALETTE_1,

64);// 设置面板按钮为按钮模式,默认情况下为画廊(Gallery)模式pBtn2->SetButtonMode();

pBtn2->SetAlwaysLargeImage();

pPanel1->Add(pBtn2);

CMFCRibbonPanel* pPanel2 = pCategory->AddPanel(_T("Extended"));// 对工具廊进行布局设置CMFCRibbonGallery* pBtn3 = new CMFCRibbonGallery(ID_RIBBON_PBTN_3,

_T("Resize Vertical"),2, 2, IDB_RIBBON_PALETTE_1, 64);

pBtn3->SetButtonMode();// 设置按钮模式下,下拉命令按钮容器(Gallery)的列数pBtn3->SetIconsInRow(2);

pBtn3->EnableMenuResize(TRUE, TRUE);

pPanel2->Add(pBtn3);

CMFCRibbonGallery* pBtn4 = new CMFCRibbonGallery(ID_RIBBON_PBTN_4, _T("Resize

Both"), 3, 3, IDB_RIBBON_PALETTE_1, 64);

pBtn4->SetButtonMode();// 通过SetIconInRow()和EnableMenuResize()设置命令按钮的布局pBtn4->SetIconsInRow(4);

pBtn4->EnableMenuResize(TRUE);

pPanel2->Add(pBtn4);

CMFCRibbonGallery* pBtn5 = new CMFCRibbonGallery(ID_RIBBON_PBTN_5, _T("Groups &&

Subitems"), 4, 4);// 通过AddGroup()函数,对命令按钮进行分组pBtn5->AddGroup(_T("Group 1"), IDB_RIBBON_PALETTE_1, 64);

pBtn5->AddGroup(_T("Group 2"), IDB_RIBBON_PALETTE_2, 64);

pBtn5->SetButtonMode();

pBtn5->SetIconsInRow(4);

pBtn5->EnableMenuResize(TRUE);// 在按钮中添加子项目(按钮)pBtn5->AddSubItem(new

CMFCRibbonButton(ID_RIBBON_MENU_ITEM_1, _T("Item 1")));

pBtn5->AddSubItem(new CMFCRibbonButton(ID_RIBBON_MENU_ITEM_2, _T("Item 2")));

pBtn5->AddSubItem(new CMFCRibbonButton(ID_RIBBON_MENU_ITEM_3, _T("Item 3")));

pPanel2->Add(pBtn5);

工具栏

在传统的菜单式界面中,工具栏作为菜单的有益补充,被广泛使用。我们通过将一些常用命令放置到工具栏上,可以让用户直观而快速地访问到常用功能,提高了效率。在Ribbon界面中,工具栏得到了进一步的加强。除了具备原来的工具栏功能外,因为使用命令按钮实现,还使得工具栏具备了下拉菜单等扩展功能。

图7 工具栏

如下的代码演示了如何创建Ribbon界面中的工具栏控件:

CMFCRibbonPanel* pPanel1 = pCategory->AddPanel(_T("From Toolbar"));// 最简单的,通过AddToolBar()函数,指定一个工具栏资源而创建工具栏pPanel1->AddToolBar(IDR_TOOLBAR);// 手动创建工具栏CMFCRibbonPanel* pPanel2 =

pCategory->AddPanel(_T("Manual"));// 创建一个按钮组CMFCRibbonButtonsGroup*

pButtonsGroup1 = new CMFCRibbonButtonsGroup;// 将新的按钮添加到按钮组中pButtonsGroup1->AddButton(new CMFCRibbonButton(ID_RIBBON_GBTN_1, _T(""), 0));

pButtonsGroup1->AddButton(new CMFCRibbonButton(ID_RIBBON_GBTN_2, _T(""), 1));//

创建一个编辑框控件CMFCRibbonEdit* pEdit = new CMFCRibbonEdit(ID_RIBBON_GBTN_3,

65);// 设置默认文本pEdit->SetEditText(_T("Edit"));

pButtonsGroup1->AddButton(pEdit);

pButtonsGroup1->AddButton(new CMFCRibbonButton(ID_RIBBON_GBTN_4, _T(""), 2));

pButtonsGroup1->AddButton(new CMFCRibbonButton(ID_RIBBON_GBTN_5, _T(""), 3));//

将按钮组添加到面板中pPanel2->Add(pButtonsGroup1);// 添加新的按钮组和按钮CMFCRibbonButtonsGroup* pButtonsGroup2 = new CMFCRibbonButtonsGroup;

pButtonsGroup2->AddButton(new CMFCRibbonButton(ID_RIBBON_GBTN_6, _T(""), 4));

pButtonsGroup2->AddButton(new CMFCRibbonButton(ID_RIBBON_GBTN_7, _T(""), 5));

pButtonsGroup2->AddButton(new CMFCRibbonButton(ID_RIBBON_GBTN_8, _T(""), 6));

pButtonsGroup2->AddButton(new CMFCRibbonButton(ID_RIBBON_GBTN_9, _T(""), 7));

pPanel2->Add(pButtonsGroup2);

CMFCRibbonButtonsGroup* pButtonsGroup3 = new CMFCRibbonButtonsGroup;

CMFCRibbonButton* pBtn10 = new CMFCRibbonButton(ID_RIBBON_GBTN_10, _T(""), 8);

pBtn10->SetMenu(IDR_RIBBON_MENU_1);

pButtonsGroup3->AddButton(pBtn10);

CMFCRibbonButton* pBtn11 = new CMFCRibbonButton(ID_RIBBON_GBTN_11, _T(""), 9);//

为按钮指定一个子菜单pBtn11->SetMenu(IDR_RIBBON_MENU_1, TRUE);

pButtonsGroup3->AddButton(pBtn11);

pPanel2->Add(pButtonsGroup3);

编辑框

在传统的软件界面中,我们都是通过点击菜单项,或者工具栏上的按钮来简单执行某个命令。在新的Ribbon界面中,我们不仅可以点击按钮,还可以通过编辑框输入数据或者通过ComboBox快速地选择数据等等,完成更加复杂的交互。

图8 编辑框

如下的代码演示了Ribbon编辑框的创建过程:

CMFCRibbonPanel* pPanel1 = pCategory->AddPanel(_T(“Standard"));

// 创建简单编辑框

CMFCRibbonEdit* pBtn1 = new CMFCRibbonEdit(ID_RIBBON_EBTN_1, 90);

pBtn1->SetEditText(_T("Edit"));

pPanel1->Add(pBtn1);

// 创建可调编辑框

CMFCRibbonEdit* pBtn2 = new CMFCRibbonEdit(ID_RIBBON_EBTN_2, 90);

pBtn2->EnableSpinButtons(0, 99);

pBtn2->SetEditText(_T("0"));

pPanel1->Add(pBtn2);

// 创建ComboBox

CMFCRibbonComboBox* pBtn3 = new CMFCRibbonComboBox(ID_RIBBON_EBTN_3, TRUE, 74);

// 添加下拉选项

pBtn3->AddItem(_T("Combo Box"));

for (i = 0; i < 20; i++)

{

CString str;

(_T("Item %d"), i + 1);

pBtn3->AddItem(str);

}

pBtn3->SelectItem(0);

pPanel1->Add(pBtn3);

CMFCRibbonPanel* pPanel2 = pCategory->AddPanel(_T("With Icons and Labels"));

// 创建带图标的编辑框

CMFCRibbonEdit* pBtn4 = new CMFCRibbonEdit(ID_RIBBON_EBTN_4, 90, _T("Label:"),

0);

pBtn4->SetEditText(_T("Edit"));

pPanel2->Add(pBtn4);

CMFCRibbonEdit* pBtn5 = new CMFCRibbonEdit(ID_RIBBON_EBTN_5, 90, _T("Label:"),

1);

pBtn5->EnableSpinButtons(0, 99);

pBtn5->SetEditText(_T("0"));

pPanel2->Add(pBtn5);

CMFCRibbonComboBox* pBtn6 = new CMFCRibbonComboBox(ID_RIBBON_EBTN_6, TRUE, 74,

_T("Label:"), 2);

pBtn6->AddItem(_T("Combo Box"));

for (i = 0; i < 20; i++)

{

CString str;

(_T("Item %d"), i + 1);

pBtn6->AddItem(str);

}

pBtn6->SelectItem(0);

pPanel2->Add(pBtn6);

CMFCRibbonPanel* pPanel3 = pCategory->AddPanel(_T("Font"));

// 创建字体选择ComboBox

CMFCRibbonFontComboBox::m_bDrawUsingFont = TRUE;

CMFCRibbonFontComboBox* pBtn7 = new CMFCRibbonFontComboBox(ID_RIBBON_EBTN_7);

pBtn7->SelectItem(_T("Arial"));

pPanel3->Add(pBtn7);

其他控件

除了前面我们介绍的按钮,工具栏,编辑框等基本控件外,为了支持现代软件对丰厚的界面交互方式的要求,Visual Studio 2010还提供了很多其他的辅助控件,例如我们通常会用到的“上一步”按钮,标签文本,超链文本,滑动条,进度条等等。这些辅助控

件,极大地丰富了Ribbon界面的表现力。

图9 其他控件

如下代码演示了其他各种控件的创建过程:

// 添加“上一步”按钮

CMFCRibbonPanel* pPanel1 = pCategory->AddPanel(_T("Undo"));

CMFCRibbonUndoButton* pBtn1 = new CMFCRibbonUndoButton(ID_RIBBON_OBTN_1,

_T("Undo"), 0, 0);// 为返回按钮添加可以返回的动作for (int i = 0; i < 10; i++)

{

CString str;

(_T("Action %d"), i + 1);

pBtn1->AddUndoAction(str);

}

pPanel1->Add(pBtn1);// 添加文本标签

CMFCRibbonPanel* pPanel2 = pCategory->AddPanel(_T("Label"));

pPanel2->Add(new CMFCRibbonLabel(_T("Label 1")));

pPanel2->Add(new CMFCRibbonLabel(_T("Label 2")));

pPanel2->Add(new CMFCRibbonLabel(_T("Label 3")));// 在面板中添加一个分隔符

pPanel2->Add(new CMFCRibbonSeparator());// 多行文本标签

pPanel2->Add(new CMFCRibbonLabel(_T("This is a multi-line label"), TRUE));// 添加超链标签

CMFCRibbonPanel* pPanel3 = pCategory->AddPanel(_T("Hyperlink"));// 写mail给我啊

pPanel3->Add(new CMFCRibbonLinkCtrl(ID_RIBBON_OBTN_2, _T("Send e-mail"),

_T("mailto:chenlq@")));// 欢迎访问我的blog

pPanel3->Add(new CMFCRibbonLinkCtrl(ID_RIBBON_OBTN_3, _T("Visit site"),

_T("/17237043/")));

pPanel3->Add(new CMFCRibbonLinkCtrl(ID_RIBBON_OBTN_4, _T("Launch Notepad"),

_T("notepad")));// 滑动条

CMFCRibbonPanel* pPanel4 = pCategory->AddPanel(_T("Sliders"));

pPanel4->SetCenterColumnVert();

pPanel4->Add(new CMFCRibbonLabel(_T("Simple Slider:")));

pPanel4->Add(new CMFCRibbonSlider(ID_RIBBON_OBTN_5, 70 /* Slider width */));

pPanel4->Add(new CMFCRibbonSeparator());

pPanel4->Add(new CMFCRibbonLabel(_T("Slider with Buttons:")));

CMFCRibbonSlider* pBtn6 = new CMFCRibbonSlider(ID_RIBBON_OBTN_6, 70 /* Slider width

*/);// 设置缩放按钮

pBtn6->SetZoomButtons();

pBtn6->SetRange(0, 100);

pBtn6->SetPos(50);

pPanel4->Add(pBtn6);// 进度条

CMFCRibbonPanel* pPanel5 = pCategory->AddPanel(_T("Progress Bars"));

pPanel5->SetCenterColumnVert();// 简单进度条

pPanel5->Add(new CMFCRibbonLabel(_T("Simple Progress:")));

pPanel5->Add(new CMFCRibbonProgressBar(ID_RIBBON_OBTN_7, 100 /* Bar width */));

pPanel5->Add(new CMFCRibbonButton(ID_RIBBON_OBTN_8, _T("Show Progress 1")));

pPanel5->Add(new CMFCRibbonSeparator());

pPanel5->Add(new CMFCRibbonLabel(_T("Infinite Progress:")));

CMFCRibbonProgressBar* pBtn9 = new CMFCRibbonProgressBar(ID_RIBBON_OBTN_9, 100 /*

Bar width */);// 设置为无限模式,表示动作在进行,但是没有明确的进度

pBtn9->SetInfiniteMode();

pPanel5->Add(pBtn9);

pPanel5->Add(new CMFCRibbonButton(ID_RIBBON_OBTN_10, _T("Show Progress 2")));

到此为止,我们已经演练了Ribbon界面的大多数控件。通过这些实际代码的演练,我相信大家现在都可以自信地说:

“I can Ribbon now!”