现在的位置: 首页 > 综合 > 正文

无敌的Word CommandBar和它的Control们

2013年10月07日 ⁄ 综合 ⁄ 共 4435字 ⁄ 字号 评论关闭

                Word 2007在外观上和Word 2003比,改动很大。一个叫Ribbon的控件容器取代了过去Office版本中的菜单和工具栏。在Word 2003中,我们可以使用VBA, VSTO, Office Automation等等各种各样的技术,在菜单或者工具栏上添加自定义的按钮,实现我们想要的功能。C#版本的Automation代码,大致如下:

            //Initial and show Word Application

            Word.Application wordApp = new Microsoft.Office.Interop.Word.Application();

            wordApp.Visible = true;

 

            //Create a Command Bar

            Office.CommandBar commandBar = wordApp.CommandBars.Add("My Bar",

                Office.MsoBarPosition.msoBarTop, false, true);

            commandBar.Visible = true;

 

            //Add a Command Bar button

            Office.CommandBarButton btn = commandBar.Controls.Add(Office.MsoControlType.msoControlButton,

                missing, missing, missing, true) as Office.CommandBarButton;

            btn.Caption = "My Button";

            btn.Tag = "MyButton";

            btn.Style = MsoButtonStyle.msoButtonCaption;

            btn.Click += new _CommandBarButtonEvents_ClickEventHandler(btn_Click);

 

            void btn_Click(CommandBarButton Ctrl, ref bool CancelDefault)

            {

                MessageBox.Show("My button is clicked!");

            }

代码很简单,需要注意的地方是,buttonTag属性一定要赋值,还有添加button方法的最后一个参数设置为true,否则,当Word关闭的时候,添加的button将留在Word的工具栏上,下次打开Word会添加新的buttonbutton越来越多,这会让人想砸电脑。(可以通过删了Normal.dot把这些残留button删掉,当然还有其它方法)

以上的代码在Word 2003里跑,毫无疑问,工作正常。但是如果在只安装了Word 2007的机器上跑呢?Word 2007是没有MenuToolbar的,只有一个叫Ribbon的东西,Ribbon里面又有很多的TabTab里面再分GroupGroup里才是各种各样的控件。测试的结果是,在2007里面,以上的代码运行完全正常!看到的结果是,在Ribbon上多了一个叫Add-InsTabTab里是Custom Toolbars组,最里面就是我们添加的My Button按钮了。可见微软兼容了2007Ribbon和过去版本中的Toolbar。事实上,对于CommandBarWord对象模型中的结构,20072003没有什么大的区别,这也是上面的代码可以在两个Word版本中正常工作的原因。我们看到的Ribbon,只不过基于xml的方式,将工具栏中的控件重新组织并展现出来。如果用VSTO做过Ribbon的扩展开发,就会发现,其实Ribbon的实现,就是用一个xml文件去描述,如何将各个控件显示出来,Label是什么,图片是什么,描述是什么,以及响应事件的回调函数又是什么。这个话题比较远,我以后还会写其他的文章来介绍。

在做Office扩展开发的时候,我们很多很多很多情况下会,必须和工具栏上的按钮打交道。这样,知道每个工具栏,还有按钮的名字就很重要。微软提供了Office2007System Control ID列表供下载,这极大地方便了程序员。(下载的地址:http://www.microsoft.com/downloads/details.aspx?FamilyID=4329D9E9-4D11-46A5-898D-23E4F331E9AE&displaylang=en ) 这些列举了所有控件IDexcel文件,极其有用,但是也有它的局限性,它是针对于Ribbon的。所以在用xml扩展Ribbon的时候,这是一个很好的参考手册。但是当我们想直接通过CommandBar来实现一些功能的时候,很多控件的名字是对不上号的。

自己动手,丰衣足食,写一个很简单,却又很有用的小程序,把Office 2007CommandBar和它里面的控件都挖出来,看看它们的真面目:

            //Create Word Application

            Word.Application wordApp = new Microsoft.Office.Interop.Word.Application();

 

            //Create a new txt file to record controls' list

            StreamWriter sw = System.IO.File.CreateText(@"C:/Word Command Bar Control List.txt");

 

 

            //loop through wordApp.CommandBars to get all CommandBars

            foreach (Office.CommandBar cb in wordApp.CommandBars)

            {

                sw.WriteLine(cb.Name);

                //loop through each CommandBar's Controls collection to get all controls

                foreach (Office.CommandBarControl cbc in cb.Controls)

                {

                    sw.WriteLine("/t" + cbc.Caption);

                }

            }

        上面的代码在C盘生成了一个文本文件,结构式的显示出了所有的CommandBar的名字,还有他们所包含的控件的名字。一共16K,不可能贴在这儿了。得到这些CommandBarControl的名字有什么用呢?下面举两三个例子来看看,都是在论坛上被问到的问题:

1. Office2007里面,我想通过CustomTaskPane(VSTO SE提供的一个新功能,可以将WinformUserControl填充到Word内的一个板上,实现功能的扩展,该blog上将有文章介绍)上的一个按钮,来最小化WordRibbon,无论Ribbon当前的状态怎样。Word 2007的对象模型中,ActiveWindow提供了一个叫ToggleRibbon的方法,但是它只是将Ribbon的状态转换,最小化时最大化,最大化时最小化。怎么办?

自然的想法是要去判断Ribbon现在的状态是什么样的。但是找遍了整个WOM(Word对象模型),都找不到任何属性,指示了现在Ribbon的状态。绝望之中,我loop CommandBars,发现最后一个CommandBarRibbon。原来Ribbon也是CommandBars中的一员啊!把这个CommandBar的高矮胖瘦属性读出来一看,果然,最大化的时候Height属性值为147,最小化的时候值为56。哈哈,问题解决了,主要代码如下。CommandBar真好,真强大!

    In ThisAddIn.cs

private static Office.CommandBars cbs = null;

 

                private void ThisAddIn_Startup(object sender, System.EventArgs e)

                {

                        this.CustomTaskPanes.Add(new UserControl1(),"test").Visible = true;

                        cbs = this.Application.CommandBars;

                }

 

                public static Office.CommandBar returnRibbon()

                {

                    foreach (Office.CommandBar cb in cbs)

                    {

                        if (cb.Name == "Ribbon")

                        {

                            return cb;

                        }

                    }

                    return null;

                }

In CustomTaskPanes UserControl1.cs

private void button1_Click(object sender, EventArgs e)

                {

                        int i = ThisAddIn.returnRibbon().Height;

                        if (i == 147)

                        {

                                Globals.ThisAddIn.Application.ActiveWindow.ToggleRibbon();

                        }

                }

抱歉!评论已关闭.