香港电影没落 战狼:细品RibbonX(15):回调(CallBacks)

来源:百度文库 编辑:偶看新闻 时间:2024/04/29 15:15:19
回调,即使自定义界面能够工作的代码。如果没有回调,那么自定义界面可能看起来漂亮,但只是一个漂亮的功能区。当然,除内置控件不需要自定义回调外。
下面的内容介绍如何使用回调来提供自定义控件所需的功能。在编写XML代码时,需要指定回调,然后在Excel中编写VBA代码来匹配和处理回调。
回调概要
回调是自定义的用户界面使用的子过程和函数,使自定义的用户界面能够工作。回调简单地表现为所提供的指令的动向。例如,当设置某按钮的onAction属性并装载用户界面时,一旦单击该按钮,就产生回调,即在属性中指定的操作。
如果没有找到指定的操作,那么回调将失败,因为代码中发生了例外,即在属性中指定的回调在VBA中不存在,因此失败了。
自定义用户界面一装载就会调用VBA工程,搜寻指定的函数或过程。如果找到,则将其值传回到用户界面。如果没有找到指定的函数或过程,那么将产生错误的结果。
有两种主要的方式来创建回调:
n         直接在VBE的标准模块中输入过程或函数
n         使用工具生成过程,例如Office 2007 CustomUI Editor
使用诸如Office 2007 CustomUI Editor这类工具的主要优势是能够扫视XML代码并返回回调签名,也称作subprocedure stub,XML代码中每个属性都有一个需要处理的回调。接受回调作为值的属性包括onAction、getVisible和getImage。
除了节省时间外,使用CustomUI Editor还能避免由于手工编写回调签名而导致的拼写错误。上述每个属性都会产生一个不同的回调签名,必须按顺序使用代码处理,使用户界面有合适的功能。
此外,当工程装载时需要访问某些回调并运行,这意味着如果回调处理(即响应回调的VBA代码)在该工程中不存在,将产生错误消息。当然,下面的内容也会介绍如何缓解这类错误,甚至如何避免错误。
为动态回调建立文件
为了使自定义控件工作,文件必须启用宏,否则不能够添加或运行VBA代码。
1、捕获IRibbonUI对象
IRibbonUI对象引用功能区用户界面,用于控制事物如何响应。
在VBA中使用的关键之一是使整个Ribbon对象无效(因而能够改变功能区的某项特征)或者使功能区中指定的控件无效(因而能够改变该控件的某项特征)。
(1)调整XML以包括onLoad
为了使用IRibbonUI对象,需要在VBA中对其设置。首先,需要对UI的onLoad属性指定值,这能通过为onLoad属性指定回调来实现:

因为onLoad属性的值是一个回调,所以需要在VBA代码中对其进行处理。接着,能够在工程中使用IRibbonUI对象。
(2)创建VBA代码处理onLoad事件
可能会注意到,前面将onLoad称作为属性,但现在将其称为事件。这是因为在XML文件中,能为许多属性定义值,例如onAction、getLabel和onLoad。一旦为某属性赋值,如果能以某种方式触发,将导致事件发生。这就是属性和事件的区别。
因为IRibbonUI对象用于整个应用程序,所以需要在标准模块的全局声明部分对其声明,如下面的代码所示。
‘全局的ribbon对象
Dim grxIRibbonUI As IRibbonUI
这里使用标准的格式grxIRibbonUI引用IRibbonUI对象,接着添加回调来设置该对象:
Sub rxIRibbonUI_onLoad(ribbon As IRibbonUI)
Set grxIRibbonUI = ribbon
End Sub
设置为全局对象之后,该对象可用于整个工程。然而,Ribbon对象对于修改是非常敏感的。这意味着任何时候修改代码,该对象实例将丢失并且任何需要Ribbon对象的操作都将失败。因此,无论何时作出修改,都需要保存、关闭并重新打开工程。
生成第一个回调
知道需要获得回调签名后,还需要知道如何使用回调签名。例如,对于切换按钮(toggleButton)有下列签名:
Sub rxtgl_click(control as IRibbonControl,pressed as boolean)
一个普通按钮的签名如下:
Sub rxbtn_click(control as IRibbonControl)
1、从头开始编写回调
如果知道了回调签名,则不必使用标准的形式声明参数。例如,有一个使用下列XML的切换按钮:
id=”rxtgl”
label=”Toggle”
size=”large”
onAction=”rxtgl_click”
imageMso=”FormatPainter”/>
编写rxtgl_click回调如下:
Sub rxtgl_click(rxctl As IRibbonControl,toggled As Boolean)
If toggled Then
MsgBox “我已切换 …我的ID是 “ & rxctl.ID,vbInformation
End If
End Sub
注意到回调的参数名与上面介绍的标准的参数名不一样,但是单击切换按钮时仍触发该回调,像平常一样传递参数,因此签名中的修改不会导致过程失败,只要使用了正确类型的正确参数。
也能修改onLoad回调签名来满足需要,如下所示:
Sub rxIRibbonUI_onLoad(MyRibbon As IRibbonUI)
Set grxIRibbonUI=MyRibbon
End Sub
然而,如果使用标准的签名及其参数名称,那么其他人将更容易理解代码。下面列出了一些回调签名。
属性onLoad,回调签名(ribbon as IRibbonUI);
属性getLabel,getPressed,getEnabled,getImage,getScreentip,getVisible,等,回调签名(control as IRibbonControl,ByRef returnedVal);
属性onAction(切换按钮),回调签名(control as IRibbonControl,pressed as Boolean);
属性onAction(按钮),回调签名(control as IRibbonControl)。
2、使用Office CustomUI Editor生成回调
一种很容易生成回调的方法是使用CustomUI Editor。这个工具将所有的返回回调的属性搜寻在一起,然后生成需要的回调。因此,无须追踪XML中所有的回调。对于大段的XML代码来说,这是无价的。
在CustomUI Editor中(以Excel为例),可以使用下列步骤自动生成必需的回调:
步骤1 使用CustomUI Editor打开包含XML代码的Excel。
步骤2 单击“Generate Callbacks”按钮。
步骤3 出现一个新的Callbacks选项卡。复制产生的代码并粘贴到VBA工程中。
注意,确保验证代码。
3、理解文件打开时事件的顺序
在工程中添加了回调后,该文档打开时将调用某些过程,具体调用的过程取决于工程打开时定制是否获得了焦点。注意,某些过程仅当包含定制的选项卡获取焦点时才调用,而其它过程当鼠标移动到控件之上时调用。
理解过程调用的顺序是复杂的,因为调用顺序受许多可变因素影响。为了帮助预测典型的事件顺序,下表列出了功能区选项卡的事件及相应的顺序。
表:当打开工程后选项卡获取焦点时的事件顺序
事件
选项卡获取焦点
选项卡有焦点
按下ALT键
鼠标在其上方
onLoad
最顶级的事件,当装载UI时发生
getVisible
1
1
N/A
N/A
getLabel
2
3
N/A
N/A
getImage
3
4
N/A
N/A
getEnabled
4
2
N/A
N/A
getKeytip
N/A
N/A
1
N/A
getScreentip
N/A
N/A
N/A
1
getSupertip
N/A
N/A
N/A
2
上表仅列出了可以使用的通用属性的一些示例,然而顺序可能受其它引入的属性的影响,例如getDescription、getTitle,等等。虽然如此,打算在性能方面以最好的方式解决用户界面问题时,上表仍然可以作为一个通用的向导。
4、能够有具有相同名称但不同签名的两个回调吗?
VBA不允许在相同工程中使用相同名称不同签名的两个回调。然而,如果回调在不同的工程中,则相同的回调名称能够有不同的签名。因此,如果同时打开一个以上的Excel文档,那么可能发现回调返回不可预料的结果。因为如果多个操作(签名)与一个回调名称相联系,那么将运行当前文档的回调。
假设打开一个安装了两个加载项的Excel工作簿,三个项目都有一个带有称为rxbtnnsQaShared的控件的用户界面。当单击用户界面中该控件时,所期望的是添加一个新工作簿,然而将出现一个消息框。检查后,发现为所有三个按钮都使用了相同的回调。此时,可以使用断点调试,看看单击操作调用了哪个回调。
上述表明,只要在不同工程中,虽然允许使用带有不同签名相同名称的回调,但这不是一个好主意。
调用位于不同工作簿中的过程
与上面所讲的情况相似,如果XML代码运行位于不同工作簿中的VBA,也会碰到类似的问题。
假设有两个工作簿:Book.xlsm和Book2.xlsm,希望在第一个工作簿中添加一个按钮,运行第二个工作簿中的过程。使用下面的XML代码创建用户界面:



label=“My Custom Tab“
insertBeforeMso=“TabHome“>
label=“My Demo Group“>