Office中国论坛/Access中国论坛

标题: 【原创】VSTO-EXCEL-事件触发流程(写给天平大哥) [打印本页]

作者: faunus    时间: 2014-2-25 09:44
标题: 【原创】VSTO-EXCEL-事件触发流程(写给天平大哥)
本帖最后由 faunus 于 2014-2-25 10:13 编辑

【缘起】

天平大哥是我们VSTO初级班(一期)的老大哥,
学号:CA-113A-郑树晓
我不知道是否最年长的一位,却也四十开外了。
虽然刚刚开始接触到VSTO开发,
却有着不输年轻人的学习劲头,
为了弄清楚一段代码一个对像的来龙去脉,
常常会研究到深更半夜(体力好啊),
感楷于此依稀看到了我当年的影子。

其实作为初一期的班主任,
我本人并不推荐这样的学习方式,
毕境这个不是初级班需要的内容,
而大把的精力完全可以放在更有价值的项目上。

不论如何天平大哥对知识的渴求仍值得我们大家学习,
作为朋友和老师我仍然被感动了,
为此昨晚花了一小时将天平大哥的问题(如题)列于引用,
望有共同追求与爱好的同学共勉之。




作者: faunus    时间: 2014-2-25 09:49
【找代码】

VSTO真心一个好东西,

复杂自己简化你的应用,
VSTO可以看成VBA项目的一个完美包装,
提供了各种强大的功能,
把复杂的内部实现机制给予隐藏,
让你无需操心,甚至让你看不到。


可我们天平大哥偏偏想一探究竟,
一窥VSTO插件的代码最初的调用源于哪里。
好吧,VSTO也不小气,其实也很简简单单,
就在你的眼前,一个小小的隐藏功能。

[attach]53165[/attach]



作者: faunus    时间: 2014-2-25 10:01
【代码藏身处】

需要研究的文件是两个
文件一:ThisAddIn.cs
文件二:ThisAddIn.Designer.cs

这两个文件其实是一个主体,
源于c#的新特性:分部类,将一个类分割到了两个文件中。
分部类冠以 partial 关键字
文件一中的定义是:
public partial class ThisAddIn
文件二中的定义是:
public sealed partial class ThisAddIn : Microsoft.Office.Tools.AddInBase

而天平大哥真正想了解的内容,便隐藏在了文件一之中。
这里有一个属性很关键,代发了VSTO插件的启动入口:
  1. [Microsoft.VisualStudio.Tools.Applications.Runtime.StartupObjectAttribute(0)]
复制代码

呵呵找到了吧,立即动手吧,加上断点立马调式。
可是,等等,好像没效果啊。
好吧,我告诉你了,还需要动一个小小的手术,
我们需要把以下的属性给去掉,这家伙就是免调式的根源:
  1. [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
复制代码

搬走两座大山后,天平大哥终于可以见到曙光了。
为了让你能够早早上床,算了,我来吧,哈哈。


作者: faunus    时间: 2014-2-25 10:02
本帖最后由 faunus 于 2014-2-25 10:06 编辑

【调用过程-1】

@@入口
ThisAddIn(global::Microsoft.Office.Tools.Excel.ApplicationFactory factory, global::System.IServiceProvider serviceProvider)
        //AddInBase==>protected AddInBase(Factory factory, IServiceProvider serviceProvider, string primaryCookie, string identifier);
        : base(factory, serviceProvider, "AddIn", "ThisAddIn")

@@初始:构造函数
ThisAddIn-开始A!
        //Globals.Factory==>private static global::Microsoft.Office.Tools.Excel.ApplicationFactory _factory
        //factory==>global::Microsoft.Office.Tools.Excel.ApplicationFactory factory
        Globals.Factory = factory;
ThisAddIn-结束A!

@@事件:Initialize
Initialize-开始A!
        //调用基类
        base.Initialize();
                //创建Ribbon
                public RibbonTestA(): base(Globals.Factory.GetRibbonFactory())
                        InitializeComponent();
                public RibbonTestB(): base(Globals.Factory.GetRibbonFactory())
                        InitializeComponent();
        //ThisAddIn.Application==>internal Microsoft.Office.Interop.Excel.Application Application;
        //AddInBase==>protected T GetHostItem<T>(Type type, string cookie) where T : class;
        this.Application = this.GetHostItem<Microsoft.Office.Interop.Excel.Application>(typeof(Microsoft.Office.Interop.Excel.Application), "Application");
        //Globals.ThisAddIn==>private static ThisAddIn _ThisAddIn;
        Globals.ThisAddIn = this;
      
        //Enables visual styles for the application.      
        //Application==>public static void EnableVisualStyles();
        global::System.Windows.Forms.Application.EnableVisualStyles();
        //InitializeCachedData
        InitializeCachedData-开始A!
            if ((this.DataHost == null))
            {
                return;
            }
            if (this.DataHost.IsCacheInitialized) {
                this.DataHost.FillCachedData(this);
            }
        InitializeCachedData-结束A!
        //InitializeControls
        InitializeControls-开始A!
                //ThisAddIn.CustomTaskPanes==>internal Microsoft.Office.Tools.CustomTaskPaneCollection CustomTaskPanes;
                //ThisAddIn.Factory==>private static global::Microsoft.Office.Tools.Excel.ApplicationFactory _factory;
                //interface Factory==>CustomTaskPaneCollection CreateCustomTaskPaneCollection(IServiceProvider serviceProvider, IHostItemProvider hostItemProvider, string primaryCookie, string identifier, object containerComponent);
                this.CustomTaskPanes = Globals.Factory.CreateCustomTaskPaneCollection(null, null, "CustomTaskPanes", "CustomTaskPanes", this);
               
                //ThisAddIn.VstoSmartTags==>internal Microsoft.Office.Tools.SmartTagCollection VstoSmartTags;
                //ThisAddIn.Factory==>private static global::Microsoft.Office.Tools.Excel.ApplicationFactory _factory;
                this.VstoSmartTags = Globals.Factory.CreateSmartTagCollection(null, null, "VstoSmartTags", "VstoSmartTags", this);
        InitializeControls-结束A!
        //InitializeComponents
        InitializeComponents-开始A!
                //暂无
        InitializeComponents-结束A!
        InitializeData
        InitializeData-开始A!
                //暂无
        InitializeData-结束A!
Initialize-结束A!

@@事件:InitializeDataBindings
InitializeDataBindings-开始A!
        //BeginInitialization-
        BeginInitialization-开始A!
                //AddInBase==>public virtual void BeginInit();
                this.BeginInit();
                //interface CustomTaskPaneCollection==>void BeginInit();
                this.CustomTaskPanes.BeginInit();
                //interface SmartTagCollection===>void BeginInit();
                this.VstoSmartTags.BeginInit();
        BeginInitialization-结束A!
      
        //BindToData
        BindToData-开始A!
                //暂无
        BindToData-结束A!
      
        //EndInitialization
        EndInitialization-开始A!
                //interface SmartTagCollection==>void EndInit();
                this.VstoSmartTags.EndInit();
                //interface CustomTaskPaneCollection==>void EndInit();
                this.CustomTaskPanes.EndInit();
                //AddInBase==>public virtual void EndInit();
                this.EndInit();
        EndInitialization-结束A!
InitializeDataBindings-结束A!


作者: faunus    时间: 2014-2-25 10:06
【调用过程-2】


@@事件:RibbonTest
//partial class RibbonTestA
RibbonTestA_Load-开始A!
//暂无
RibbonTestA_Load-结束A!
//partial class RibbonTestB!!不执行

@@事件:FinishInitialization
FinishInitialization-开始A!
        //InternalStartup
        this.InternalStartup();
                InternalStartup-开始A!
                        this.Startup += new System.EventHandler(ThisAddIn_Startup);
                        this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
                InternalStartup-结束A!
        //OnStartup
        this.OnStartup();
                OnStartup-开始A!
                        base.OnStartup();
                                ThisAddIn_Startup-开始A!
                                        //暂无
                                ThisAddIn_Startup-结束A!
                OnStartup-结束A!
FinishInitialization-结束A!

@@激活向导
@@中间事件
@@事件:OnShutdown/用户退出

OnShutdown-开始A!
        //ThisAddIn==>internal Microsoft.Office.Tools.SmartTagCollection VstoSmartTags;
        //interface IDisposable==>void Dispose();
        this.VstoSmartTags.Dispose();
        //ThisAddIn==>internal Microsoft.Office.Tools.CustomTaskPaneCollection CustomTaskPanes;
        //interface IDisposable==>void Dispose();
        this.CustomTaskPanes.Dispose();
        base.OnShutdown
                ThisAddIn_Shutdown-开始A!
                        //暂无
                ThisAddIn_Shutdown-结束A!
OnShutdown-结束A!

@@完全退出




作者: faunus    时间: 2014-2-25 10:20
【不是结束是开始】


大哥,小弟其实是在害你,
从你此会踏上一条不归路。


【VSTO的调用过程,详见此处】
【原创】VSTO加载过程分析
http://www.office-cn.net/thread-117892-1-1.html

作者: 心随你动    时间: 2014-2-25 10:23
传说中的沙发。
作者: tianping    时间: 2014-2-25 10:24

谢谢老师
激动ing,无以言表
作者: microfaint    时间: 2014-2-25 10:34
膜拜。大哥给我们做了榜样。感动。帖子的内容极专业精干,是大家学习的榜样。路漫漫兮其修远,吾将上下而求索。共勉。
作者: faunus    时间: 2014-2-25 10:48
贴子的顺序乱掉了?
作者: tianping    时间: 2014-2-26 01:27
faunus 发表于 2014-2-25 10:20
【不是结束是开始】

又看了一遍,虽不能全懂,但也慢慢有些理解。
老师的知识,是多年艰苦探索的结晶,又是我多年感兴趣却自学不会的。
老师现在无私的传授给我们,学生们都心存感激,会把握好这幸运的机会。
学海无涯,这条路我要一直走下去。
谢谢老师!
作者: 醉酒狂生    时间: 2014-2-26 09:35
faunus 发表于 2014-2-25 10:48
贴子的顺序乱掉了?

因为天平老哥哥过于激动导致的
作者: tianping    时间: 2014-3-19 19:48
又看了一遍。
每次看都有点收获。
虽然对工厂、Global还不太懂,
作者: oldyuan    时间: 2014-5-7 21:38
tianping 发表于 2014-3-19 19:48
又看了一遍。
每次看都有点收获。
虽然对工厂、Global还不太懂,

第一天进群就听到天平哥的传说,今天终于了解了天平哥的事迹。感动之余又带惭愧。一定要好好向天平哥学习!




欢迎光临 Office中国论坛/Access中国论坛 (http://www.office-cn.net/) Powered by Discuz! X3.3