高级基础知识: 在 Visual Basic 中使用 RibbonX

在 Visual Basic 中使用 RibbonX
Ken Getz

在 2007 年 2 月的《MSDN 杂志》 中,Eric Faller 演示了如何使用 RibbonX API 和 XML 标记为 2007 Microsoft® Office system 创建扩展插件(见 msdn.microsoft.com/msdnmag/issues/07/02/RibbonX)。在同一期杂志中,Paul Stubbs 介绍了针对 2007 Office system 应用程序(尤其是针对 PowerPoint® 2007)的托管加载项,并且 说明了如何使用 Visual Studio® 2005 Tools for Office Second Edition 来创建这些托管加载项。在本期专栏中,我会再接再厉,以上面两位的优秀成果为基础,设法预见您在处理 RibbonX 和创建自己的功能区自定义时将可能遇到的一些问题。
请记住,由于 2007 Office system 及 Visual Studio 2005 均不提供真正的功能区设计器,因此为其创建自定义需要一些额外工作。在创建您的功能区自定义时,没有良好的用户界面可供使用;您的所有工作都要使用 XML 以及 .NET 兼容代码或 Visual Basic® for Applications (VBA) 代码完成。(Visual Studio Tools for Office 的下一版本将提供功能区的设计器。(有关详细信息,请参见本期杂志中 Steve Fox 和 Paul Stubbs 中的文章。)有关 2007 Office system 功能区的一般详细信息,请访问 msdn.microsoft.com/office/tool/ribbon。您将在此找到 Microsoft 提供的关于使用和自定义 2007 Office system 功能区的最新信息。

准备工作
要使用功能区上的各种控件,您需要了解与每一功能区元素相对应的标识符(也就是 msoID 属性)。请下载“2007 Office System 文档:控件 ID 列表”。此下载(格式为 Excel® 2003 或 Excel 2007)包括一系列电子表格,其中含有对每一功能区元素的全面公开信息。若无这些信息,要对现有功能区进行修改是近乎不可能的。请注意,如果在“选项”对话框的“自定义”窗格中,将鼠标置于某一控件上方,也可获得该控件的 ID。
请确保在您的开发计算机上有一份描述 RibbonX 的 XML 架构。凭借该架构(名为 customUI.xsd),Visual Studio 2005 XML 编辑器可以在您创建功能区自定义标记时提供 IntelliSense®。您可以下载“2007 Office System:XML 架构参考”。该下载包括 customUI.xsd 文件及针对该文件和 2007 Office system 使用的其他架构的参考资料。一旦您下载并提取了 customUI.xsd,请将其复制到 %Program Files%Microsoft Visual Studio 8XmlSchemas 文件夹。(将前面路径中的 %Program Files% 替换为您计算机中 Program Files 文件夹的位置。)在将该架构文件安装于此文件夹后,Visual Studio 2005 将在您创建新的功能区自定义文件时为您提供该架构。
如果您想将该功能区自定义保存为 Word 2007、Excel 2007 或 PowerPoint 2007 文档的一部分,以 VBA 代码处理功能区回调,您通常必须使用可处理 ZIP 文件处理工具将该文档打开,创建自定义部分,然后建立与该部分的必要关系。这一工作量相当大,您可以下载 OpenXMLDeveloper.org 提供的 Custom UI Editor Tool 以减轻工作量。虽然该工具无法帮您创建功能区自定义,但它却能在以下几个重要方面为您提供帮助:它可以将自定义插入 Word、Excel 或 PowerPoint 文档或模板中,建立必要的部分和关系;它可以将图标插入文档中以供您的自定义使用;它可以根据 custumUI.xsd 验证 RibbonX 标记;并且它还可以生成 VBA 样式的回调处理程序存根,这样您就无需查询回调过程的确切格式。即使在您创建 Visual Studio Tools for Office (VSTO) 加载项或共享的 Visual Studio COM 加载项时,最后两项功能也很有用。
当然,您还需要文档。MSDN® 在线提供了由 Frank Rice 与我合写的三篇系列文章,其中包括示例、参考资料和常见问题解答。在 Microsoft 为 RibbonX 统一提供完整的帮助文件之前,这些文章是很好的起步材料。您可以在第一篇第二篇第三篇获得这些文章。
最后,您需要考虑将您的功能区自定义存储于何处。正如在三篇文章的第一篇中所述,您有若干选项。您可以将该 RibbonX 标记直接保存于 Word、Excel 或 PowerPoint 文档之中,创建自定义 UI 部分,并设立与该部分的关系;您还可以使用我之前提到的 CustomUI Editor Tool 来帮助您将自定义 UI 插入文档中。关于针对 Access? 2007 功能区的自定义,您可以将 XML 标记存储于表中,而且您可以使用代码来检索并激活自定义。您还可以将自定义存储于 USysRibbons 表中,Access 可以在您的数据库加载的同时加载该自定义。这些备选方法中的每一种都会创建一个基于文档或模板的自定义。
如果您想创建基于应用程序的自定义,您需要考虑创建一个针对 2007 Office system 应用程序的 COM 加载项;要创建该加载项,您可以使用 Visual Studio 2005 Shared Add-in 模板,或使用 Visual Studio 2005 Tools for Office Second Edition(该方法更简单、可靠)。同样,第一篇 MSDN 文章说明了如何使用这两种方法。
获得所有工具和文档后,您就完成了准备工作,可以创建自己的 RibbonX 自定义了。尽管当您浏览本期专栏时,您可能没有使用全部这些工具和文档,但当您创建自己的自定义时,它们将证明自己的重要价值。
由于无论在何处存储内容,XML 标记都是相同的,因此我选择了允许您使用托管代码来处理功能区回调的最简单解决方案 — 也就是说,我将使用 VSTO 2005 SE 创建 Excel 2007 的加载项。(如果您未安装 VSTO 2005 SE,您可以在该产品的入口网站 msdn2.microsoft.com/aa905543.aspx 下载该产品,并获得更多信息。)

创建示例加载项
作为第一步,您需要使用 VSTO 2005 SE 创建并测试一个简单的加载项。我将快速总结上文提到的三篇 MSDN 文章中第一篇所提供的指南,这些指南将教您创建一个 Excel 加载项,而非 Word 加载项。有关更详细的说明,请参见全文。
首先,在 Visual Studio 2005 中创建一个新项目。在“新建项目”对话框的“项目类型”窗格中,展开“Office”节点,并选择“2007 加载项”。在“模板”窗格中,选择“Excel 加载项”。将新的加载项命名为 RibbonAddin,然后单击“确定”以创建该加载项。(请注意此加载项模板同时创建了加载项项目和设置项目。目前,暂时不要理会该设置项目。该设置项目可以简化加载项的部署,但对于本演示而言没有必要。)
在“项目”菜单上,单击“添加新项”,然后在对话框中选择“功能区支持”。单击“添加”以接受默认名称 Ribbon1.vb。除了文件 Ribbon1.vb 之外,该模板还添加了一个名为 Ribbon1.xml 的 XML 文件,您将稍后对其进行修改。在“项目”菜单上,单击“RibbonAddin 属性”。单击“资源”选项卡,然后从“解决方案资源管理器”中将 Ribbon1.xml 拖放至“资源”设计图面之上。关闭“资源”窗口,并保存资源。
在“解决方案资源管理器”中,双击 Ribbon1.xml 并查看其内容。默认标记,如图 1 所示,在“加载项”选项卡上创建了一个名为“我的组”的新组。该组包括一个名为“我的按钮”的切换按钮。按下该按钮将调用 OnToggleButton1 回调过程。

高级基础知识: 在 Visual Basic 中使用 RibbonX - 夏 - 隨心漂泊~~~  Figure 1 Ribbon1.xml

复制代码

<customUI    xmlns=http://schemas.microsoft.com/office/2006/01/customui        <ribbon>      <tabs>        <tab idMso=”TabAddIns”>          <group                  label=”My Group”>            <toggleButton                           size=”large”                          label=”My Button”                          screentip=”My Button Screentip”                                                    imageMso=”HappyFace” />          </group>        </tab>      </tabs>    </ribbon>  </customUI>  

在“解决方案资源管理器”中,取消 Ribbon1.vb 文件内的 ThisAddIn 局部类的注释。在 Ribbon1 类中,修改 GetCustomUI 过程,以使其返回新资源的值,如下所示:

复制代码

Return My.Resources.Ribbon1  

提供的 GetResourceText 辅助过程可手动打开 XML 内容,并使用阅读器检索文本。如果您愿意,可以在此时删除该过程。
在大多数情况下,您需要能在功能区自定义内引用宿主应用程序,所以请在 Ribbon1 类中添加下列声明:

复制代码

Public Application As Excel.Application  

您还需要初始化此变量,所以当该过程创建了 Ribbon1 类的实例之后,立刻在 ThisAddIn 类的 RequestService 方法中添加下列代码:

复制代码

ribbon.Application = Application  

展开代码中的“功能区回调”区域,然后检查 OnLoad 回调过程:

复制代码

Public Sub OnLoad(ByVal ribbonUI As Office.IRibbonUI)      Me.ribbon = ribbonUI  End Sub  

此过程取得传递给 Ribbon1 实例的 Office.IRibbonUI 值,并将其存储起来,这样以后的回调也可以与功能区进行交互。若无此步骤,您将无法执行一些重要的操作,例如在更改项目内容后刷新功能区。
此外,您还将找到那个回调过程的示例,它处理由 XML 标记创建的切换按钮的按下和释放功能。每当您按下或释放这个新的切换按钮时,它就会显示一条相应的警告:

复制代码

Public Sub OnToggleButton1( _    ByVal control As Office.IRibbonControl, _    ByVal isPressed As Boolean)      If isPressed Then          MessageBox.Show(“Pressed”)      Else          MessageBox.Show(“Released”)      End If  End Sub  

虽然我在这里稍微修改了指南内容,但如果您需要更完整的说明,应该仍可按照原文步骤操作。现在,保存并运行您的项目,确认 Visual Studio 启动了 Excel 2007。选择“加载项”选项卡,按下然后释放“我的按钮”切换按钮。每次按下和释放该按钮后,您都将看到加载项显示的警告。
对于本期专栏中的其他演示,您将修改 Ribbon1.xml 中的内容,并且为 Ribbon1 类添加更复杂的回调过程。尽管您或许可以对功能区进行无数种操作,但限于文章篇幅,我在这里仅演示两个有趣的 API 用途。
首先,假设您想要显示自己的库,该库包含由可用颜色组成的子集,以便用户可以给单元格填充背景颜色。要实现这一点,您要创建自己的颜色库。图 2 显示了该颜色库的外观。其次,我将说明,您如何使用复选框(如图 2 左上角所示)来控制是否让颜色库可用。

图 2 使用 RibbonX 创建您自己的库 

创建一个自定义颜色库
虽然用户可以从如图 3 所示的 Excel FillColor 库中选择填充颜色,但是您可能希望将颜色选择限制在一个特定子集中。要实现这一点,您可以创建自己的颜色库。然而,如果您检查 Excel FillColor 库,您可能会发现访问该库比访问图 2 中的库更容易;区别在于,当您单击 SplitButton 控件时,Excel 库就会出现,但您创建的库却必须挂在一个菜单之下。如果能将库直接创建为一个拆分按钮的子按钮,情况就好了,但是根据 customui.xsd 架构,SplitButton 控件只能包含一个按钮或切换按钮以及一个菜单。您创建的示例将库控件挂在一个简单的菜单之下。

图 3 Excel FillColor 库 
要开始使用您创建的加载项,应将 Ribbon1.xml 的内容替换为图 4 中的标记。比起从本期专栏的网络版中将内容直接复制下来,亲自动手将这些代码从头输入下来可能对您更具指导意义。在创建 RibbonX 标记时,熟悉 IntelliSense 为您提供帮助的方式非常有用。此代码创建了自定义,在启动时调用您已创建的 onLoad 过程。此外,该标记还创建一个名为 demoTab 的新选项卡,显示文本“Ribbon Customization”。该标记在选项卡内创建一个名为“库控件”的组,并在该组内创建一个 splitButton 控件,该控件包含一个按钮和一个菜单。该按钮使用内建的 CellFillColorPicker ID 来提供图像。通过仔细阅读包含 Excel 功能区控件 ID 的工作手册(从上文提到的 Microsoft 网站下载),我获得了该控件的真实 ID。这时,保存并运行该加载项以验证该行为。

高级基础知识: 在 Visual Basic 中使用 RibbonX - 夏 - 隨心漂泊~~~  Figure 4 Ribbon1.xml 的新内容

复制代码

<?xml version=”1.0” encoding=”utf-8” ?>  <customUI     xmlns=http://schemas.microsoft.com/office/2006/01/customui         <ribbon>      <tabs>        <tab label=”Ribbon Customization” >          <group label=”gallery Control”>              <splitButton >                <button                   imageMso=”CellFillColorPicker”/>                <menu >                </menu>              </splitButton>          </group>        </tab>      </tabs>    </ribbon>  </customUI>  

通过将图 5 中的元素插入 <menu> 元素的主体,继续修改标记。此标记创建了库控件,并使用了该控件几乎所有的可用回调过程。首先,该标记指定了标签,并指明该控件不应显示项目标签(在该例中,您只要显示颜色而无需显示标签)。此外,该代码指定了将在库内显示的行数和列数。通过指定回调过程,该标记指定了库属性的其余部分 — 当 Excel 2007 呈现功能区自定义时,它调用此处所列的每一过程以满足其检索数据的需要。(例如,当它需要确定某一项目的宽度时,它就调用 GetItemWidth 方法。)此外,该标记指定了将在库的底部显示的按钮。您可以拥有任意数量的这类按钮,但本例仅需要一个。

高级基础知识: 在 Visual Basic 中使用 RibbonX - 夏 - 隨心漂泊~~~  Figure 5 库控件

复制代码

<gallery     label=”Select Color”    showItemLabel=”false”    columns=”5” rows=”3”        getEnabled=”GetEnabled”     getItemCount=”GetItemCount”     getItemHeight=”GetItemHeight”     getItemWidth=”GetItemWidth”     getItemImage=”GetItemImage”     getItemScreentip=”GetItemScreenTip”>    <button       label=”No color”             screentip=”Remove color”       supertip=”Remove any applied color.”/>  </gallery>  

为了实现该库控件的行为,您现在必须提供标记中列出的每一回调过程。为此,在代码编辑器窗口中打开 Ribbon1.vb,并找到“功能区回调”区域。虽然您不一定非要将代码放在这一区域,但这么做有助于您组织代码。在接下来的段落中,我将向您讲述所有所需回调过程的创建。
请注意,您不必使用这些回调过程中的任何一个。相反,您可以为每种不同的库控件属性提供静态值。也就是说,您可以提供 itemHeight 属性以及一个固定值,而不必指定标记中的 getItemHeight 属性。此示例将代码用于每个属性,这样您就可以动态更改库的布局。
为了显示该库,您将需要颜色列表,因此请将下列代码插入 Ribbon1 类:

复制代码

Private image As New Bitmap(25, 25)  Private colors As Color() = _    {Color.Yellow, Color.GreenYellow, Color.Turquoise, _     Color.Magenta, Color.Blue, Color.Red, Color.DarkBlue, _     Color.Teal, Color.Green, Color.Violet, Color.DarkRed, _     Color.YellowGreen, Color.Gray, Color.DarkGray, Color.Black}  

此代码创建一个类级别的位图实例,您将使用该实例创建代表不同填充颜色的不同图像和一组颜色值。请您务必将此段代码和代码的其余部分插入 Ribbon1 类,而非 ThisAddIn 局部类。

创建 GetEnabled
在 Ribbon1.vb 中,添加下列回调过程。此过程与此特殊回调所需的签名相匹配。如果您的回调不匹配正确的签名,2007 Office system 应用程序将无法调用该过程:

复制代码

Public Function GetEnabled( _         ByVal control As Office.IRibbonControl) As _             Boolean         Dim returnValue As Boolean = False       Select Case control.Id         Case “highlightGallery”           returnValue = True       End Select       Return returnValue     End Function  

要查找此(及其他所有)回调过程的签名,请参考前面提及的三篇文章中的第三篇。
2007 Office system 将对触发该回调的控件的引用作为一个参数传递给 GetEnabled 方法,该示例代码使用此信息以创建一个基于调用方 Id 属性的 Select Case 语句。通过使用一个类似于此的设计模式,您可以创建一个单一的 GetEnabled 回调过程,该回调过程可以与任何共享相同回调过程签名的功能区控件共同合作。在本例中,该过程仅返回 True,表明库应该被启用。

创建 GetItemCount
getItemCount 回调允许您计算要在库中显示的项目数量,并且如果您希望指定要显示项目的数量,则必须为创建的每一库指定该回调过程。在您的加载项中,请将下列过程插入 Ribbon1 类:

复制代码

Public Function GetItemCount( _   ByVal control As Office.IRibbonControl) As Integer    Dim returnValue As Integer = 0      Select Case control.Id      Case “highlightGallery”        returnValue = 15    End Select    Return returnValue  End Function  

与之前一样,该回调收到对触发回调的控件的引用,并返回一个标量值,指明将在库中显示的项目的数量。
如果您不喜欢这种方法(即在每一回调中包括一个 Select Case 代码块,并使用调用控件的 Id 属性来确定过程的行为),可以仅为共享回调的每一控件创建一个独立的回调过程。我喜欢以这种方式整合行为,但是这当然并非必须。

创建 GetItemHeight 和 GetItemWidth
您的代码将指定库中每一项目的高度和宽度。每一项目的的大小必须相同,且该大小由您先前创建的位图实例控制。因此,请将图 6 中的回调过程添加至 Ribbon1 类,以将正确的大小返回给 Excel。

高级基础知识: 在 Visual Basic 中使用 RibbonX - 夏 - 隨心漂泊~~~  Figure 6 GetItemHeight 和 GetItemWidth

复制代码

Public Function GetItemHeight( _   ByVal control As Office.IRibbonControl) As Integer      Dim returnValue As Integer = 0    Select Case control.Id      Case “highlightGallery”        returnValue = image.Height    End Select    Return returnValue  End Function    Public Function GetItemWidth( _   ByVal control As Office.IRibbonControl) As Integer      Dim returnValue As Integer = 0    Select Case control.Id      Case “highlightGallery”        returnValue = image.Width    End Select    Return returnValue  End Function  

创建图像
虽然您可以轻易地从磁盘或资源文件为每一库项目加载图像,但该示例仅需要不同的色块。GetItemImage 回调过程因此需要使用合适的颜色为每一库项目绘制一个实心色块。GetItemImage 回调过程不仅收到对触发回调的控件的引用,还收到一个索引,指明它应该返回哪个图像。请将图 7 中所示的回调过程插入 Ribbon1 类。

高级基础知识: 在 Visual Basic 中使用 RibbonX - 夏 - 隨心漂泊~~~  Figure 7 GetItemImage

复制代码

Public Function GetItemImage( _   ByVal control As Office.IRibbonControl, _   ByVal index As Integer) As Object      Select Case control.Id      Case “highlightGallery”        Using g As Graphics = Graphics.FromImage(image)          Using brush As New SolidBrush(colors(index))            g.DrawRectangle(Pens.Gray, _              New Rectangle(0, 0, image.Width - 1, image.Height - 1))            g.FillRectangle(brush, _              New Rectangle(1, 1, image.Width - 2, image.Height - 2))          End Using        End Using    End Select    Return image  End Function  

GetItemImage 过程从您先前创建的位图中创建一个 Graphics 对象,并使用提供的值创建一个新的实心笔刷,以对颜色数组进行索引。该代码绘制一个比位图稍小的灰色矩形,然后用适当的颜色填充该矩形。

创建屏幕提示并测试加载项
当您将鼠标置于每一图像的上方时,Excel 应该显示该颜色的名称。GetItemScreenTip 回调过程要求为每一图像显示文本,而您的任务仅仅是返回每一颜色的名称。出于方便,我选择了使用 GetItemScreenTip,但实际上 GetItemLabel 可能是个更好的选择,因为它允许有视觉障碍的用户获得库项目的标签 — 即使这些标签因为其 showItemLabel 属性而不可见。如果未明确提供屏幕提示,项目将自动使用其标签作为屏幕提示。请将下列过程加入 Ribbon1 类,以添加该行为:

复制代码

Public Function GetItemScreenTip( _   ByVal control As Office.IRibbonControl, _   ByVal index As Integer) As String      Dim returnValue As String = String.Empty    Select Case (control.Id)      Case “highlightGallery”        returnValue = colors(index).Name    End Select    Return returnValue  End Function  

此时,您已经提供了为了显示库而需要的所有回调过程。保存并运行您的项目。Visual Studio 将加载 Excel 2007,当您选择功能区上的“功能区自定义”选项卡时,您会找到您的 splitButton 控件。单击下拉箭头,选择菜单项,会显示您的库。但是,单击库上的任何按钮,您都将收到错误 — 因为您尚未提供库中处理按钮单击的回调过程。您需要退出 Excel,并返回至 Visual Studio,以完成加载项的这一部分。

添加操作回调
该项针对您自定义的标记包括两个“操作”回调:针对库本身的 InsertFillColor 和针对位于库底部的按钮的 RemoveFillColor。为了避免在选择库按钮或库的底部按钮时出现错误,请将下列回调过程添加至 Ribbon1 类:

复制代码

Public Sub InsertFillColor( _   ByVal control As Office.IRibbonControl, _   ByVal selectedId As String, ByVal index As Integer)      CType(Application.Selection, Excel.Range).Interior.Color = _          ColorTranslator.ToOle(colors(index))  End Sub    Public Sub RemoveFillColor( _   ByVal control As Office.IRibbonControl)      CType(Application.Selection, Excel.Range). _         Interior.Color = Excel.Constants.xlNone  End Sub  

请注意,这两个过程使用不同的签名:第一个过程处理库控件的 OnAction 回调,而第二个处理按钮控件的 OnAction 回调。库的 OnAction 回调不仅提供对控件的引用和您所选库内项目的索引,还提供包含一个 ID 的字符串。此 selectedId 参数是所选项目的 ID,而控件的 Id 属性就是库本身的属性。
InsertFillColor 和 RemoveFillColor 回调过程都是专门针对此库的,所以我不必费神在这些过程中使用 Select Case 代码段。此外,这两个过程将 Application.Selection 值转换为一个 Excel.Range,并将 Interior.Color 属性设置为所选颜色或根本没有颜色。ColorTranslator.ToOle 方法负责将来自 System.Drawing.Color 托管类型的颜色转换为 VBA 和 Excel 可以理解的颜色。
要测试加载项,请再次保存并运行该项目。当您从库中选择一个项目时,您的加载项将把所选范围的填充颜色设置为您所选择的颜色。单击库底部的按钮会清除所选范围的所有颜色。
此时,您已创建了一个简单的功能区自定义,它充分展现了许多可用的不同回调。如果您希望根据用户输入来启用或禁用库,该怎么办呢?例如,如果您希望在功能区上有一个复选框控件可允许您控制库的可用性,这该如何实现?我接下来将添加这一稍微复杂的功能。

添加功能区控件交互
如果您要创建 Windows 应用程序,让一个复选框改变另一控件的启用状态非常简单。在相应的事件处理程序中,设置控件的 Enabled 属性,然后运行时环境会处理细节。甚至在使用 ASP.NET 创建 Web 应用程序时,您也不用担心控件的启用状态变化的具体细节 — 您只需设置一个属性,在您下次强制页面重绘时,ASP.NET 运行时环境会管理该控件的呈现。
不过,与许多其他环境不同,功能区控件编程不允许您与控件的属性直接交互。作为最佳的替代方法,您能做的就是设置一个本地变量的状态,使您想更改其属性的控件无效,并使控件的回调过程按照您的要求呈现控件。
为了演示这种行为,在您的功能区自定义上添加一个复选框控件,并让复选框的选中状态来决定库控件的启用状态。在 Ribbon1.xml 文件中,在已存在的组元素内,在已存在的 splitButton 元素下方,添加下列标记:

复制代码

<checkBox label=”Enable Color Selection?”     screentip=”Enable color selection”         supertip=”Select to enable or disable color selection.”     getPressed=”GetPressed”/>  

该 onAction 属性指定了当用户选中或取消选中复选框时您想要调用的回调过程,而 getPressed 属性则指定了当功能区初始化复选框的值时将要调用的回调。
在 Ribbon1 类中,添加一个可以维持复选框的当前选中状态的变量:

复制代码

Private enableColors As Boolean = False  

修改已现有的 GetEnabled 过程,这样该方法将返回 enableColors 变量的值,而不是简单地返回 True:

复制代码

returnValue = enableColors  

为了确保复选框控件的状态反映 enableColors 变量的值,请添加下列回调过程。2007 Office system 功能区在初始化复选框控件状态时调用该代码:

复制代码

Public Function GetPressed( _   ByVal control As Office.IRibbonControl) As Boolean      Dim returnValue As Boolean = True    Select Case control.Id      Case “enableColorsCheckBox”        returnValue = enableColors    End Select    Return returnValue  End Function  

最后,您需要一些方法来处理用户选中或取消选中复选框时的状况。诀窍就在于既设置 enableColors 变量的值,同时又强制功能区使库控件无效。通过使控件无效,您可以强制其重新初始化,适当设置控件的启用状态:

复制代码

Public Sub HandlePressedAction( _   ByVal control As Office.IRibbonControl, _   ByVal pressed As Boolean)      Select Case control.Id      Case “enableColorsCheckBox”        enableColors = pressed        ribbon.InvalidateControl(“highlightGallery”)    End Select  End Sub  

使库控件无效的该行代码展示了功能区自动化的两个重要方面:第一,如果加载项尚未存储初始化时传递给它的对功能区的引用,您就无法在以后的过程中与功能区交互。因此,这就是功能区代码处理 OnLoad 回调,存储对于其传递给一个类级别变量的功能区的引用之所以重要的原因。此外,该示例代码还演示了 IRibbonUI 接口的 InvalidateControl 方法。您可以调用 InvalidateControl 方法,传递一个特定控件以使之无效,或者您可以调用 Invalidate 方法(并使整个功能区无效)。无论采用二者中的哪种方法,您都必须调用这些过程的一个,从而告知功能区,它必须重绘一个或所有控件。
与先前一样,保存并运行项目。在 Excel 2007 中,选择功能区上的“功能区自定义”选项卡,除了现有的 splitbutton 控件之外,您还会发现新的复选框。尝试显示库,您会发现菜单项被禁用了。选中复选框,再次尝试显示库,这次库的状态变为可用了。
正如您所看到的,基于功能区本身的体系结构,功能区控件之间的交互可能比您预想的要多费些功夫。如果您不想为功能区添加其他控件,您可以减小代码的大小 — 每一回调过程中的 Select Case 语句为以后扩展代码提供方便,但这并不是必需的。
您可以对许多基于功能区的不同情景使用相同的技巧。在任何情况下,当您需要根据一个不同控件的“事件”来修改任何控件的布局、行为或内容时,请使用类级别的变量来维持状态,并使控件或整个功能区无效。
我原以为自己不会喜欢新的用户界面,但我发现自己错了 — 功能区采用了一种很好的方式向用户提供选择,而且声明性模型比旧的 Office CommandBar 模型更加便于编程。

请将您想向 Ken 询问的问题或提出的意见发送至  basics@microsoft.com.

Ken Getz是 MCW Technologies 的高级顾问和 AppDev 的课件作者。他与人合作编写了《ASP.NET 开发人员入门》(Addison-Wesley, 2002)、《Access 开发人员手册》(Sybex, 2002) 和《VBA 开发人员手册》 第二版 (Sybex, 2001)。请发送电子邮件至 keng@mcwtech.com 与他联系。

引文来源  高级基础知识: 在 Visual Basic 中使用 RibbonX