WorldWind学习系列五:插件加载过程全解析

it2024-10-30  16

  不得不承认World Wind的代码真的很庞大,没有太多帮助文档的前提下,一头钻进代码里肯定令你头疼的,甚至研究代码间关联仿佛是在走迷宫。我最近一直想弄明白如何在MenuBar中加载那些插件的,WorldWind学习系列四中研究的只是特殊的三个功能加载的,那三个没有继承Plugin类,不算是插件功能加载。所以WorldWind学习系列四加载的三个是特殊情况,不是一般的插件加载。今天下午终于柳暗花明,如果你真正关注World Wind分析,那么就好好看看下面的插件加载过程全解析。

      我们先看看Plugin类的继承图,看看到底都有些什么插件,然后在分析一般性的插件加载全过程。

 

  哦,原来这么多插件,我们要基于WW开发自己的应用,只需继承Plugin类写出自己的插件功能即可的。      我们现在分析插件加载过程,请确保你看过 WorldWind学习系列二:擒贼先擒王篇2 中的(5.加载上次使用的配置信息)。加载的插件入口就是WorldWind.cs的Main()中调用的LoadSettings()静态方法。   1.读取WorldWind的配置中插件信息 加载WorldWind配置 private   static   void  LoadSettings()        {             try             {      //先读取上次使用时保存的“使用插件配置文件”,如果存在,则从文件中读取配置实例化WorldWindSettings                 Settings  =  (WorldWindSettings) SettingsBase.Load(Settings, SettingsBase.LocationType.User);                 if ( ! File.Exists(Settings.FileName))                {             //我们假定是配置文件不存在,这就是一个个地加载插件,保存到ArrayList中                      Settings.PluginsLoadedOnStartup.Add( " ShapeFileInfoTool " );                     // Settings.PluginsLoadedOnStartup.Add("OverviewFormLoader");                     // Settings.PluginsLoadedOnStartup.Add("Atmosphere");                     Settings.PluginsLoadedOnStartup.Add( " SkyGradient " );                    Settings.PluginsLoadedOnStartup.Add( " BmngLoader " );                     // Settings.PluginsLoadedOnStartup.Add("Compass");                     // Settings.PluginsLoadedOnStartup.Add("ExternalLayerManagerLoader");                     Settings.PluginsLoadedOnStartup.Add( " MeasureTool " );                     // Settings.PluginsLoadedOnStartup.Add("MovieRecorder");                     Settings.PluginsLoadedOnStartup.Add( " NRLWeatherLoader " );                    Settings.PluginsLoadedOnStartup.Add( " ShapeFileLoader " );                    Settings.PluginsLoadedOnStartup.Add( " Stars3D " );                    Settings.PluginsLoadedOnStartup.Add( " GlobalClouds " );                    Settings.PluginsLoadedOnStartup.Add( " PlaceFinderLoader " );                    Settings.PluginsLoadedOnStartup.Add( " LightController " );                    Settings.PluginsLoadedOnStartup.Add( " Earthquake_2.0.2.1 " );                    Settings.PluginsLoadedOnStartup.Add( " Historical_Earthquake_2.0.2.2 " );                    Settings.PluginsLoadedOnStartup.Add( " KMLImporter " );                     // Settings.PluginsLoadedOnStartup.Add("doublezoom");                     // Settings.PluginsLoadedOnStartup.Add("PlanetaryRings");                     Settings.PluginsLoadedOnStartup.Add( " TimeController " );                     // Settings.PluginsLoadedOnStartup.Add("WavingFlags");                     Settings.PluginsLoadedOnStartup.Add( " ScaleBarLegend " );                    Settings.PluginsLoadedOnStartup.Add( " Compass3D " );                    Settings.PluginsLoadedOnStartup.Add( " AnaglyphStereo " );                    Settings.PluginsLoadedOnStartup.Add( " GlobeIcon " );                }                 //  decrypt encoded user credentials                 DataProtector dp  =   new  DataProtector(DataProtector.Store.USE_USER_STORE);                 if (Settings.ProxyUsername.Length  >   0 ) Settings.ProxyUsername  =  dp.TransparentDecrypt(Settings.ProxyUsername);                 if (Settings.ProxyPassword.Length  >   0 ) Settings.ProxyPassword  =  dp.TransparentDecrypt(Settings.ProxyPassword);            }             catch (Exception caught)            {                Log.Write(caught);            }        }

 

  2.Main()中后面调用MainApplication()方法,该MainApplication()调用OpenStartupWorld(),用来初始化启动World对象。OpenStartupWorld()方法首先确定加载的是Earth/Moon等,然后开始加载一个星球。

 

加载一个星球代码          ///   <summary>          ///  Loads a new planet         ///   </summary>          private   void  OpenWorld( string  worldXmlFile)        {                         if ( this .worldWindow.CurrentWorld  !=   null )            {                 try                 {                     this .worldWindow.ResetToolbar();                }                 catch                 {}                 try                 {                     foreach (PluginInfo p  in   this .compiler.Plugins)                    {                         try                         {                             if (p.Plugin.IsLoaded)                                p.Plugin.Unload();                        }                         catch                         {}                    }                }                 catch                 {}                                 try                 {                     this .worldWindow.CurrentWorld.Dispose();                }                 catch                 {}                            }             if ( this .gotoDialog  !=   null )            {                 this .gotoDialog.Dispose();                 this .gotoDialog  =   null ;            }             if ( this .rapidFireModisManager  !=   null )            {                 this .rapidFireModisManager.Dispose();                 this .rapidFireModisManager  =   null ;            }             if ( this .animatedEarthMananger  !=   null )            {                 this .animatedEarthMananger.Dispose();                 this .animatedEarthMananger  =   null ;            }             if ( this .wmsBrowser  !=   null )            {                 this .wmsBrowser.Dispose();                 this .wmsBrowser  =   null ;            }             worldWindow.CurrentWorld  =  WorldWind.ConfigurationLoader.Load(worldXmlFile, worldWindow.Cache);              this .splashScreen.SetText( " Initializing menus... " );             // InitializePluginCompiler()是我们要关注的初始化插件编辑器PluginCompiler(真正管理加载插件的类)              InitializePluginCompiler();                 //RenderableObject系统很复杂,我们稍后准备专门分析一下              foreach (RenderableObject worldRootObject  in   this .worldWindow.CurrentWorld.RenderableObjects.ChildObjects)            {                 this .AddLayerMenuButtons( this .worldWindow, worldRootObject);            }             //加载Earth专有的MenuButton( AnimatedEarthManager和RapidFireModisManager)的配置,             //这里主要不关注              this .AddInternalPluginMenuButtons();             this .menuItemModisHotSpots.Enabled  =  worldWindow.CurrentWorld.IsEarth;             this .menuItemAnimatedEarth.Enabled  =  worldWindow.CurrentWorld.IsEarth;        }

 

  3.我们看看InitializePluginCompiler()如何加载插件的?

初始化PluginCompiler          ///   <summary>          ///  Compile and run plug-in "scripts"         ///   </summary>          private   void  InitializePluginCompiler()        {            Log.Write(Log.Levels.Debug,  " CONF " " initializing plugin compiler... " );             this .splashScreen.SetText( " Initializing plugins... " );             string  pluginRoot  =  Path.Combine(DirectoryPath,  " Plugins " );            compiler  =   new  PluginCompiler( this , pluginRoot); // #if DEBUG             //  Search for plugins in worldwind.exe (plugin development/debugging aid)             compiler.FindPlugins(Assembly.GetExecutingAssembly()); // #endif         //从启动文件夹下Plugins文件夹,加载插件             compiler.FindPlugins();        //加载启动插件插件              compiler.LoadStartupPlugins();         }

 

  4.加载启动插件函数的代码

加载启动插件 ///  Loads the plugins that are set for load on world wind startup.         ///   </summary>          public   void  LoadStartupPlugins()        {             foreach (PluginInfo pi  in  m_plugins)            {                 if (pi.IsLoadedAtStartup)                {                     try                     {                         //  Compile                         Log.Write(Log.Levels.Debug, LogCategory,  " loading  " + pi.Name + "  ... " );                        worldWind.SplashScreen.SetText( " Initializing plugin  "   +  pi.Name);       //Load()方法加载插件,Plugin类的Load()为虚方法,实质上调用的是各个插件重载后的Load()方法                          Load(pi);                     }                     catch (Exception caught)                    {                         //  Plugin failed to load                          string  message  =   " Plugin  "   +  pi.Name  +   "  failed:  "   +  caught.Message;                        Log.Write(Log.Levels.Error, LogCategory, message);                        Log.Write(caught);                         //  Disable automatic load of this plugin on startup                         pi.IsLoadedAtStartup  =   false ;                        worldWind.SplashScreen.SetError(message);                    }                }            }        }

 

  5.现在看两个插件类重载的Load()方法的实例。例如:Compass3D.cs和TimeController.cs。

  Compass3D.cs的Load()方法

重载后的Load方法  21行      public   override   void  Load()        {            m_menuItem  =   new  System.Windows.Forms.MenuItem( " Compass " );            m_menuItem.Click  +=   new  EventHandler(m_menuItem_Click);            m_menuItem.Checked  =  World.Settings.ShowCompass;            ParentApplication.ToolsMenu.MenuItems.Add(m_menuItem);                        m_form  =   new  FormWidget( " Compass " );            m_form.ClientSize  =   new  System.Drawing.Size( 200 200 );            m_form.Location  =   new  System.Drawing.Point( 0 400 );            m_form.BackgroundColor  =  World.Settings.WidgetBackgroundColor;            m_form.AutoHideHeader  =   true ;            m_form.VerticalScrollbarEnabled  =   false ;            m_form.HorizontalScrollbarEnabled  =   false ;            m_form.BorderEnabled  =   false ;        //注册两个窗体事件             m_form.OnResizeEvent  +=   new  FormWidget.ResizeHandler(m_form_OnResizeEvent);             m_form.OnVisibleChanged  +=   new  VisibleChangedHandler(m_form_OnVisibleChanged);             //实例化Compass3DWidget            m_compass  =   new  Compass3DWidget();            m_compass.Location  =   new  System.Drawing.Point( 5 0 );            m_compass.Font  =   new  System.Drawing.Font( " Ariel " 10.0f , System.Drawing.FontStyle.Bold);            m_compass.ParentWidget  =  m_form;            m_form_OnResizeEvent(m_form, m_form.WidgetSize);                        m_form.ChildWidgets.Add(m_compass);            m_form.Visible  =  World.Settings.ShowCompass; //将要绘制的Widget加载到DrawArgs.NewRootWidget.ChildWidgets,为了在WorldWindow.cs的Render()方法里渲染             DrawArgs.NewRootWidget.ChildWidgets.Add(m_form);        //Compass 3D工具菜单按钮             m_toolbarItem  =   new  WorldWind.NewWidgets.WidgetMenuButton(                     " Compass 3D " ,                    basePath  +   " \\Data\\Icons\\Interface\\compass2.png " ,                    m_form);       //向MenuBar中添加Compass 3D菜单按钮              ParentApplication.WorldWindow.MenuBar.AddToolsMenuButton(m_toolbarItem);              base .Load();        }

 

  TimeController.cs的Load方法,如下:

TimeController.cs的Load方法 时间控制 public   override   void  Load()        {             try             {                m_window  =   new  WorldWind.NewWidgets.FormWidget( " Time Control " );                m_window.Name  =   " Time Control " ;                m_window.ClientSize  =   new  System.Drawing.Size( 300 183 );                 //  Bug in FormWidget required anchor to be set before Location and parent widget                 m_window.Anchor  =  WorldWind.NewWidgets.WidgetEnums.AnchorStyles.Left  |  WorldWind.NewWidgets.WidgetEnums.AnchorStyles.Bottom;                m_window.ParentWidget  =  DrawArgs.NewRootWidget;                m_window.Location  =   new  System.Drawing.Point( 0 , DrawArgs.NewRootWidget.ClientSize.Height  -   183 );                m_window.Text  =   " Double Click to Re-Open " ;                m_window.BorderEnabled  =   false ;                m_window.AutoHideHeader  =   true ;                m_window.BackgroundColor  =  System.Drawing.Color.FromArgb( 0 0 0 0 );                m_window.HeaderEnabled  =   true ;                m_window.Visible  =   false ;                time  =   new  WorldWind.NewWidgets.PictureBox();                time.Name  =   " Time " ;                time.ImageUri  =  basePath  +   " \\Data\\Icons\\Time\\time off.png " ;                time.ClientLocation  =   new  System.Drawing.Point( 12 59 );                time.ClientSize  =   new  System.Drawing.Size( 42 42 );                time.Visible  =   true ;                time.ParentWidget  =  m_window;                time.OnMouseEnterEvent  +=   new  EventHandler(time_OnMouseEnterEvent);                time.OnMouseLeaveEvent  +=   new  EventHandler(time_OnMouseLeaveEvent);                time.OnMouseUpEvent  +=   new  MouseEventHandler(time_OnMouseUpEvent);                time.CountHeight  =   false ;                time.CountWidth  =   true ;                m_window.ChildWidgets.Add(time);                play  =   new  WorldWind.NewWidgets.PictureBox();                play.Name  =   " Play " ;                 if  (TimeKeeper.Enabled)                {                    play.ImageUri  =  basePath  +   " \\Data\\Icons\\Time\\play on.png " ;                }                 else                 {                    play.ImageUri  =  basePath  +   " \\Data\\Icons\\Time\\play off.png " ;                }                play.ClientLocation  =   new  System.Drawing.Point( 50 1 );                play.ClientSize  =   new  System.Drawing.Size( 82 82 );                play.Visible  =   true ;                play.ParentWidget  =  m_window;                play.OnMouseEnterEvent  +=   new  EventHandler(play_OnMouseEnterEvent);                play.OnMouseLeaveEvent  +=   new  EventHandler(play_OnMouseLeaveEvent);                play.OnMouseUpEvent  +=   new  System.Windows.Forms.MouseEventHandler(play_OnMouseUpEvent);                play.CountHeight  =   true ;                play.CountWidth  =   true ;                m_window.ChildWidgets.Add(play);                close  =   new  WorldWind.NewWidgets.PictureBox();                close.Name  =   " Close " ;                close.ImageUri  =  basePath  +   " \\Data\\Icons\\Time\\close off.png " ;                close.ClientLocation  =   new  System.Drawing.Point( 29 3 );                close.ClientSize  =   new  System.Drawing.Size( 22 22 );                close.Visible  =   true ;                close.ParentWidget  =  m_window;                close.OnMouseEnterEvent  +=   new  EventHandler(close_OnMouseEnterEvent);                close.OnMouseLeaveEvent  +=   new  EventHandler(close_OnMouseLeaveEvent);                close.OnMouseUpEvent  +=   new  MouseEventHandler(close_OnMouseUpEvent);                close.CountHeight  =   false ;                close.CountWidth  =   false ;                m_window.ChildWidgets.Add(close);                rewind  =   new  WorldWind.NewWidgets.PictureBox();                rewind.Name  =   " Rewind " ;                rewind.ImageUri  =  basePath  +   " \\Data\\Icons\\Time\\repeat off.png " ;                rewind.ClientLocation  =   new  System.Drawing.Point( 16 26 );                rewind.ClientSize  =   new  System.Drawing.Size( 32 32 );                rewind.Visible  =   true ;                rewind.ParentWidget  =  m_window;                rewind.OnMouseEnterEvent  +=   new  EventHandler(rewind_OnMouseEnterEvent);                rewind.OnMouseLeaveEvent  +=   new  EventHandler(rewind_OnMouseLeaveEvent);                rewind.OnMouseUpEvent  +=   new  MouseEventHandler(rewind_OnMouseUpEvent);                rewind.CountHeight  =   false ;                rewind.CountWidth  =   false ;                m_window.ChildWidgets.Add(rewind);                pause  =   new  WorldWind.NewWidgets.PictureBox();                pause.Name  =   " Pause " ;                 if  (TimeKeeper.Enabled)                {                    pause.ImageUri  =  basePath  +   " \\Data\\Icons\\Time\\pause off.png " ;                }                 else                 {                    pause.ImageUri  =  basePath  +   " \\Data\\Icons\\Time\\pause on.png " ;                }                pause.ClientLocation  =   new  System.Drawing.Point( 35 88 );                pause.ClientSize  =   new  System.Drawing.Size( 64 64 );                pause.Visible  =   true ;                pause.ParentWidget  =  m_window;                pause.OnMouseEnterEvent  +=   new  EventHandler(pause_OnMouseEnterEvent);                pause.OnMouseLeaveEvent  +=   new  EventHandler(pause_OnMouseLeaveEvent);                pause.OnMouseUpEvent  +=   new  System.Windows.Forms.MouseEventHandler(pause_OnMouseUpEvent);                pause.CountHeight  =   true ;                pause.CountWidth  =   false ;                m_window.ChildWidgets.Add(pause);                slow  =   new  WorldWind.NewWidgets.PictureBox();                slow.Name  =   " Slow " ;                slow.ImageUri  =  basePath  +   " \\Data\\Icons\\Time\\slow off.png " ;                slow.ClientLocation  =   new  System.Drawing.Point( 97 88 );                slow.ClientSize  =   new  System.Drawing.Size( 64 64 );                slow.Visible  =   true ;                slow.ParentWidget  =  m_window;                slow.OnMouseEnterEvent  +=   new  EventHandler(slow_OnMouseEnterEvent);                slow.OnMouseLeaveEvent  +=   new  EventHandler(slow_OnMouseLeaveEvent);                slow.OnMouseUpEvent  +=   new  System.Windows.Forms.MouseEventHandler(slow_OnMouseUpEvent);                slow.CountHeight  =   false ;                slow.CountWidth  =   false ;                m_window.ChildWidgets.Add(slow);                fast  =   new  WorldWind.NewWidgets.PictureBox();                fast.Name  =   " Fast " ;                fast.ImageUri  =  basePath  +   " \\Data\\Icons\\Time\\fast off.png " ;                fast.ClientLocation  =   new  System.Drawing.Point( 158 88 );                fast.ClientSize  =   new  System.Drawing.Size( 64 64 );                fast.Visible  =   true ;                fast.ParentWidget  =  m_window;                fast.OnMouseEnterEvent  +=   new  EventHandler(fast_OnMouseEnterEvent);                fast.OnMouseLeaveEvent  +=   new  EventHandler(fast_OnMouseLeaveEvent);                fast.OnMouseUpEvent  +=   new  System.Windows.Forms.MouseEventHandler(fast_OnMouseUpEvent);                fast.CountHeight  =   false ;                fast.CountWidth  =   false ;                m_window.ChildWidgets.Add(fast);                timeLabel  =   new  WorldWind.NewWidgets.TextLabel();                timeLabel.Name  =   " Current Time " ;                timeLabel.ClientLocation  =   new  System.Drawing.Point( 134 65 );                timeLabel.ClientSize  =   new  System.Drawing.Size( 140 60 );                timeLabel.Visible  =   true ;                timeLabel.ParentWidget  =  m_window;                timeLabel.Text  =  GetCurrentTimeString();                TimeKeeper.Elapsed  +=   new  System.Timers.ElapsedEventHandler(TimeKeeper_Elapsed);                timeLabel.CountHeight  =   false ;                timeLabel.CountWidth  =   true ;                timeLabel.WordBreak  =   true ;                m_window.ChildWidgets.Add(timeLabel);                DrawArgs.NewRootWidget.ChildWidgets.Add(m_window);                 m_toolbarItem  =   new  WorldWind.NewWidgets.WidgetMenuButton(                     " Time Controller " ,                     basePath  +   " \\Data\\Icons\\Time\\time off.png " ,                     m_window);      //向MenuBar中添加菜单按钮                 ParentApplication.WorldWindow.MenuBar.AddToolsMenuButton(m_toolbarItem);             }             catch  (Exception ex)            {                Log.Write(ex);            }             base .Load();        }

 

其他插件的重载后的Load()方法也是类似的,不再赘述。希望能帮研究WW的朋友理清插件加载过程的思路,少走弯路。

其他部分:

WorldWind学习系列四:功能分析——Show Planet Axis、Show Position 、Show Cross Hairs功能

WorldWind学习系列三:简单功能分析——主窗体的键盘监听处理及拷贝和粘贴位置坐标功能

WorldWind学习系列三:功能分析——截屏功能和“关于”窗体分析

WorldWind学习系列二:擒贼先擒王篇2

WorldWind学习系列二:擒贼先擒王篇1

WorldWind学习系列一:顺利起航篇

 

 

   

转载于:https://www.cnblogs.com/wuhenke/archive/2009/12/13/1623078.html

相关资源:数据结构—成绩单生成器
最新回复(0)