|||
update: 2017-11-18 增加极简介绍
先来点极简介绍:
1.看看我的电脑上EXCEL的弹出菜单是不是有点不一样?
2.背后的XML规定是这样的.
以下讲讲怎么做,例子与上面有所不同.
---------------------
你想根据自己的需要隐藏掉弹出菜单中某些不常用的菜单项吗? 抑或是增加一些自己需要的特定功能,或者在弹出菜单下增加“上标”、“下标”、“保存”等常用的命令? 如果是,请往下看,我这里要讲的就是“定制“自己的个性化弹出菜单。
该技术不仅适用于WORD,也适用EXCEL,Powerpoint等Office应用程序。 文中以Excel为例 。
微软自Office 2007起采用了Ribbon风格的控件,这种方式条理清晰,易于学习(对新手来讲,对老手反而是个麻烦).后期在Office2013, 2016还提供了对Ribbon界面的自定义修订, 使用起来很方便. 可惜的是, 不知为何,微软取在Office2007之后取消了原来比较便捷的右键弹出菜单的自定义方式,即通过”自定义-快捷菜单”来调出自定义界面,现在这个方式不支持了.
不过,Office其实并没有关上自定义弹出菜单的大门.还是有几种方法可以对弹出菜单(或Ribbon界面)进行自定义的。
第一种方法: 通过VBA编程或VSTO编程或加装外部插件. 可以对弹出菜单进行来各种定义的. 不过普通用户如果没有掌握VBA或VSTO编程,这一技术有点复杂。因为不是本文的重点,这里不作解释。 不过,网上可以搜索到非常多的用VBA编程来定制菜单的方法和代码。
'删除WORD的弹出菜单中不常用的"同义词库" 菜单项.
Sub HideThesaurusButton()
For i = 1 To CommandBars("Text").Controls.Count
If InStr(CommandBars("Text").Controls(i).Caption, "同义词") > 0 Then
CommandBars("Text").Controls(i).Delete
Beep
Exit For
End If
Next i
End Sub
第二种方法. 通过编辑XML文件自定义界面. 也是本文要讲的重点.
在Office 2007起, 它提供了一种新的自定义方式,即通过XML文件来定义office的界面, 也包括对弹出菜单的订制.
先讲一下具体的操作程序[①]
1.在桌面新建一个目录,名为 customUI.(这个目录名可以是其它名字,只要保证第10步建立文档与自定义界面的关系时写法一致即可以,这里用这个名字演示)
2.使用文本编辑器创建自定义界面的文件. (不要用Windows自带的记事本,可以用UltraEdit, Emeditor, Notepad2, Notepad++等文本编辑器) 编辑XML内容,具体做法下面详述.文件保存为 customUI.xml (或其它名字), 保存到刚才创建的customUI目录. 如果有中文的内容,请注意用UTF-8格式保存. 用ANSI编码保存中文可能在打开时出错.后面详述.
3.验证编写的XML标记是否合规(可选).
4.在Office应用中新建一个文件,随便输入一点内容,然后保存为OfficeOpen XML格式文件,也就是扩展名最后是x或m的文件格式. (如 .docx,.docm, .xlsx, .xlsm, .pptm, 或 .pptx). 文件中有VBA代码(“宏”)的要保存为含m后缀的格式(如.docm, .dotm,.xlsm,.xltm,pptm), 这种格式允许存放能够为Ribbon扩展命令和组件调用的VBA代码.
5.退出Office应用.
6.在资源管理器中,给刚才保存的文件(如XXX.docm, yyy.xlsm等)的扩展名末尾再增加一个后缀.zip, 把它变成一个ZIP文件.然后双击,作为一个压缩文件夹打开.
这里有人可能觉得有点费解,为什么docm文件加上.zip后缀就可以打开? 其实背后的逻辑很简单,所谓的 .docm 或.xlsm文件本身实际上就是一个ZIP格式的文件, 采用.docm或.xlsm只是为了方便office程序识别它们是WORD或EXCEL的数据文件.因此将其后缀改为ZIP并没有问题,可以正常打开.
7.将customUI目录拖放到上面的压缩文件夹中. (将自定义文件加入到文件容器).
8.将压缩文件夹下的_rels 目录拖放到桌面. _rels 目录包含了.rels 文件(这个文件没有文件名,只有一个后缀,但是可以在文本编辑器中正常的打开和编辑, 注意不要修改这个文件名)
9.用文本编辑器打开这个.rels 文件.
10.在.rels文件最末尾的 <Relationship> 元素和封闭的 <Relationships>元素之间(注意后面这个标签带有s), 加入一行语句, 以创建文档文件和自定义文件的关系. 例如
<<Relationship Id="Rb4af401bff6346e8" Type="http://schemas.microsoft.com/office/2007/relationships/ui/extensibility" Target="DxhcustomUI/DxhModifiedUI.xml" />
注意: 这里Target后面的值是自定义界面的文件的相对路径.这个要与第1步的文件名和路径都相符. 即你刚才在ZIP压缩文件夹里放的自定义界面文件,如CustomUI.xml(或随便其它名字);注意XML是区分大小写的; id值可以任意指定,有唯一性即可.
这一步其实很关键,它告诉Office这个定义文件放在哪个目录,写错了Office找不到XML定义,就只好调用默认的设置了,你的订制效果就出不来.
11.保存.rels 文件.
12.将修改过的.rels 从桌面(刚才释放在桌面的目录里)拖放到压缩文件夹下面的_rels 目录目录,以替换掉原来的 .rels 文件.
13.去除文档刚才附加的.zip后缀,变回原来的文件名. 当你再在Office应用中打开该文件时,界面的订制效果就会出现.
以上操作的基本思路,就是 a)在rels目录下的.resl文件中增加一个关系,指定自定义界面的xml文件放在哪里. b)在指定的xml文件中编写内容,规定菜单项的调整内容.
其实上面13步, 真正的订制内容在第2步,编写XML文件来定义界面.
下面举个我已经写好的例子,是个扩展名为xml的文件.(为了充分演示例子比较长, 如果你需要订制的地方不多,完全可以不必这么复杂)
如果看不明白可以跳过直接往下看 示例
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
<contextMenus>
<contextMenu idMso="ContextMenuText">
<!--更新于2017-10-25by dingsir@qq.com -->
<!--以下为增加命令 -->
<!--增加保存按钮到菜单 -->
<button idMso="FileSave" insertBeforeMso="Cut" />
<!--粘贴文本-->
<button idMso="PasteTextOnly" insertBeforeMso="Cut" />
<!--插入脚注 -->
<button idMso="FootnoteInsert" insertBeforeMso="SymbolsDialog" />
<!--插入尾注-->
<button idMso="EndnoteInsertWord" insertBeforeMso="SymbolsDialog" />
<!--下标-->
<toggleButton idMso="Subscript" insertBeforeMso="SymbolsDialog" />
<!--上标 -->
<toggleButton idMso="Superscript" insertBeforeMso="SymbolsDialog" />
<!--分隔线-->
<menuSeparator id="MySeparator1" insertBeforeMso="Cut" />
<!--将以下几个按钮隐藏 -->
<!--粘贴选项 -->
<gallery idMso="PasteGalleryMini" visible="false" />
<!--汉字重选 -->
<button idMso="ImeReconvert" visible="false" />
<!--英语助手 -->
<button idMso="EnglishAssistance" visible="false" />
<!--翻译 -->
<button idMso="Translate" visible="false" />
<!--智能搜索 -->
<button idMso="Insights" visible="false" />
<!--超链接 -->
<button idMso="HyperlinkInsert" visible="false" />
<!--隐藏结束 -->
<menuSeparator id="MySeparator" insertBeforeMso="InsertNewComment" />
<!--增加myButton按钮-->
<button id="MyButton" label="My Button" onAction="GetButtonID" />
<!--增加子菜单 -->
<menu id="MySubMenu" label="My Submenu">
<button id="MyButton2" label="Button on submenu" onAction="btnAction" />
</menu>
<!--增加多选按钮 -->
<gallery id="galleryOne" label="MyGallery" >
<item id="item1" imageMso="HappyFace" />
<item id="item2" imageMso="HappyFace" />
<item id="item3" imageMso="HappyFace" />
<item id="item4" imageMso="HappyFace" />
</gallery>
<!--增加动态菜单,其菜单根据VBA代码动态生成,详见方法的代码-->
<dynamicMenu id="MyDynamicMenu" label="My Dynamic Menu" getContent="GetMyContent" />
</contextMenu>
</contextMenus>
</customUI>
该XML结构是这样的.
实际运行的结果是这样的
如果你需要将某个按钮或菜单项添加到弹出菜单, 需要这么几个信息:
1. 知道你要添加的弹出菜单,它在XML定义中叫什么名字.比如说WORD中处理文本的弹出菜单叫ContextMenuText, Excel中处理单元格的弹出菜单叫ContextMenuCell.
2. 知道这个按钮或菜单项的内部名字.可以通过微软提供的idMso清单找(见本文末尾的参考阅读4或本文的附件内素材),也可以在office界面定义上的提示找.前者通过英文与中文的意思,在ExcelControls.xlsx或WorkControls.xlsx中找, 这个要求你懂英文; 后者的方法更简单点,如下:
3.根据菜单命令的类型编写标记.
该XML文件支持以下控件类型.
control
button
checkBox
dynamicMenu
gallery
menu
menuSeparator
splitButton
toggleButton
注意以上示例中,如果该控件是Office自已本来就有的控件, 名字用idMso 属性来表示, 如果是用户自己新规定的,用id来表示.
(完整的XML标记语言的规范,参见末尾的扩展阅读5)
举几个例子来讲一下怎么编写xml
---------------------------------XML命令解释--------------------------------------------
增加菜单项
增加内部已定义的按钮
<button idMso="FileSave" insertBeforeMso="Cut" />
表示要增加一个FileSave按钮(即文件保存),它是内置的命令(用idMso属性指定),插入的位置在 “Cut”命令(菜单上显示为“剪切”)的前面.
如果你想规定在某命令之后插入,可以使用类似的 insertAfterMso, 将上面的Before修改为After即可.
如果你需要更改内部命令的名字,可以用label 属性来指定.比如
<button idMso="FileSave" label="保存当前文件" insertBeforeMso="Cut" />
增加一个已定义的切换按钮
<toggleButton idMso="Subscript" insertBeforeMso="SymbolsDialog" />
表示要增加一个下标按钮,插入到”插入字符”菜单项前面.
增加一个菜单分隔线
<menuSeparator id="MySeparator" insertBeforeMso="InsertNewComment" />
表示在”插入批注”前面加入一个菜单分隔线. 它的ID可以由你指定,不是内置的,所以你可以看到.这个属性是由id而不是idMso指定的.
需要用到VBA的定制
增加新定义的按钮
增加新定义的按钮或功能,需要用到VBA代码,因此,保存这些定义的文档必须是docm或xlsm或pptm这种扩展名末尾为m的文件格式. 对VBA不了解的这一节可以路过.
例如:
<button id="MyButton" label="MyButton" onAction="GetButtonID"/>
表示在菜单上增加一个名字叫MyButton的按钮,它显示的标题(你看到菜单文字)是 My Button, 点击它, 它执行的动作(过程)叫GetButtonID. GetButtonID是存放在文档中的VBA过程.它的签名(过程的标准样子) Sub OnAction(control As IRibbonControl), 实际执行的代码示例:
Sub GetButtonID(control As IRibbonControl)
MsgBox ("你刚点击了" & control.ID & " 按钮.")
End Sub
增加新定义的子菜单
<menu id="MySubMenu" label="子菜单示例">
<button id="MyButton2" label="Button2 onsubmenu" onAction="btnAction" />
<button id="MyButton3" label="Button3 onsubmenu" onAction="btnAction" />
</menu>
这是一个名称MySubMenu 标题”子菜单示例”的子菜单,它下一级包括两个按钮,按钮的标题稍有不同,但响应点击的行为都是同一个过程btnAction.
增加新定义的动态菜单
所谓动态菜单就是用户文档为Office提供一个XML格式的字符串,里面定义了菜单的样式.这个内容通过过程返回给Office,从而指导Offiice生成的新菜单项
示例:
<dynamicMenu id="MyDynamicMenu" label="My DynamicMenu" getContent="GetMyContent" />
这个过程的样式签名: Sub GetContent(controlAs IRibbonControl, ByRef content)
实际代码举例:
Sub GetMyContent(control As IRibbonControl,ByRef content)
Dim xmlString As String
xmlString = "<menu xmlns=""http://schemas.microsoft.com/office/2009/07/customui""><button id=""btn1"" imageMso=""HappyFace"" label=""Click Me"" onAction=""btnAction"" />"
xmlString = xmlString & "<menu id=""mnu"" label=""My Dynamic Menu""> " & _
"<button id=""btn2"" imageMso=""RecurrenceEdit"" /> " & _
"<button id=""btn3"" imageMso=""CreateReportFromWizard"" /> " & _
"</menu>"
content = xmlString & "</menu>"
End Sub
上述代码中,因为生成的字串在VBA中要用引号包围, 字串中的引号就得用两个引号来表示.
--------------------------------XML命令解释 结束------------------------------------
如果你不想这么麻烦,有一个工具帮你节省时间,你只需要编写自定义页面的xml文件就行,其它都由这个工具来完成 ---Office Custom UI Editor,下载地址见扩展阅读3. 由于是以前的版本没有继续更新了, 需要安装.net framework 3.0
最后,本文的内容在Office2016测试OK, 其它版本没有测试过. 内容参考或引用了以下扩展阅读的内容.
写完之后, 猛然发现,其实主要的困难都是在解释怎么编写XML文件以实现定制菜单. 弄明白之后其实也不复杂.
为方便你的试验,我提供了下面的附件, 测试文件.dotm就是含有自定义弹出菜单功能的文档. 素材 目录下还有office2016版几个主要组件的控件信息清单,可以用来查idMso值. 以及这个测试文档中有定义有关的文件及目录.
扩展阅读:
1. Customizing the 2007 OfficeFluent Ribbon for Developers
Part 1 of 3: https://technet.microsoft.com/zh-cn/library/aa338202.aspx
Part 2 of 3: https://msdn.microsoft.com/library/aa338199.aspx
Part 3 of 3: https://msdn.microsoft.com/en-us/library/aa722523(v=office.12).aspx
2. Customizing Context Menus inOffice 2010
https://msdn.microsoft.com/en-us/library/office/ee691832(v=office.14).aspx
3. Office Custom UI Editor 下载
http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2009/08/06/7293.aspx
4. 控件的内部idMso名称(即Office Fluent User Interface Control Identifiers) 下载
Office 2016: https://www.microsoft.com/en-us/download/details.aspx?id=50745
Office 2013: https://www.microsoft.com/en-us/download/details.aspx?id=36798
Office 2010: https://www.microsoft.com/en-us/download/details.aspx?id=6627
5. 微软标准 Custom UI XML Markup Specification 下载
https://msdn.microsoft.com/en-us/library/cc313070(v=office.12).aspx
[①]参考 扩展阅读1的Part1之 Customizing the Fluent UI by Using Office Open XML Formats Files 部分
Archiver|手机版|科学网 ( 京ICP备07017567号-12 )
GMT+8, 2024-11-23 17:02
Powered by ScienceNet.cn
Copyright © 2007- 中国科学报社