返回首页

基于插件技术的GIS应用框架(C# + ArcEngine9.3)

时间:2012-08-18 17:23来源:知行网www.zhixing123.cn 编辑:麦田守望者

一直想把原来用Delphi写的GIS应用框架进行升级,可由于家庭和工作牵扯了太多的精力,没能如愿,最近一段时间,终于研墨执笔开始了框架的升级工作,历时一个多月,终于新鲜出炉了,现在静下心来进行总结,以提炼我这一个多月的辛劳与汗水。


一、关于平台的选择

实际上本人一直从未用过Visual Studio,更未用C#做过一个完整的项目,其实就开发平台而言并不存在太多的差异,就像.net框架和J2EE的包,以及delphi的VCL,他们的思想其实都是大同小异的,语言使用到了一定的高度,有了一定的积累,转换到另外一种语言,困难就小多了。其实只要支持COM的语言都可以用来进行GIS框架的开发,之所以采用C#开发新版本的GIS应用框架,对于自己来说无非是两点:第一,界面更加完美;第二,就是想检验一下自己的学习能力。


二、关于ArcEngine接口的选择

这个问题我觉得很重要,看过很多人家的代码以及成型的系统,似乎都乐意采用ToolbarControl这个东西,我研究了一段时间,这个东西不仅控制麻烦,而且会带来很多负面问题,比如,我无法在ToolbarControl里加入自己的控制逻辑,而且更糟糕的是,对于想要保存自己定制内容的程序员来说,这样的封装显得太过了。此外,比如IEngineEditor接口的选择,这个接口提供了很强大的功能,对于编辑任务和编辑图层几乎可以不用写什么代码就能实现,但是编辑任务和编辑图层两个列表都必须出现在ToolbarControl中,这对于我这个追求完美的人来说,无疑是个灾难,所以在我是框架里,抛弃了ToolbarControl和IEngineEditor这个对于很多程序员来说非常方便的东西,IEngineEditor的功能基本上完全靠自己代码来实现,编辑任务、编辑图层等都以插件的形式出现在自己的框架里,既做到了界面风格统一,也做到了功能完全可以自定义。当然这背后的代价是你自己编写行数不菲的代码。


三、关于事件

开发GIS应用框架,最核心的一个问题就是事件的处理了,毕竟有了事件,所有的插件对象才能有机地构成一个整体,这也是所有插件对象进行协同工作的基础所在。COM提供了连接点的机制来进行事件的发布,而C#则较为简单,可以直接通过事件代理的形式来处理,这样一来,所有客户插件感兴趣的MapControl事件和PageLayoutControl事件即可以方便的通过事件代理来获得框架的调用。


四、关于反射

.net 的反射机制的确是个好东西,获取插件的类型信息易如反掌,只是本人没有深入研究,在这里也就不赘叙了。


五、关于插件的加载与保存

实际上有很多种方式可以对定制的结果进行保存,比如:结构化存储文件,xml等等,在本文论及的框架里,选择了后者,不光是因为插件的加载与否,如何加载只需要简单的进行XML配置就可以实现,而且也便于单独调式某个插件或某一组插件。
 

选用什么样的第三方组件库来进行插件的封装是开发GIS框架的一个重要问题,直接影响到你框架容器加载插件的方式和插件对象的管理机制;此外开发平台的选择也需要考虑,但是选择有很多种,本文论及的框架开发环境配置如下:

一、Visual Studio 2008

个人觉得比 Visual Studio 2005 运行稳定。

二、ArcEngine 9.3

当然您也可以选择9.2,或其他版本。

三、DevExpress 第三方组件库

这个第三方组件库功能忒强大,而且界面也比较华丽,说实话,不用不知道,用到后面发现还是有些问题的,不过不影响全局就是了,比如它的下拉列表,要用事件代理来发布它的事件还真让你想不到有这么麻烦,不过还好,功夫不负有心人,潜心研究还是出来结果的。建议选择其他的第三方组件库,这个真不好用。

四、.net framework

选择什么样的.net framework版本完全取决于自己,但是版本越高当然bug也就越少,功能自然也就越强大。


开发工具有了,用于实例化插件的第三方组件包也有了,.net framework也选好了,ArcEngine也敲定了,一切准备就绪,框架开发可以开始啦。
 

我们在进行GIS框架的开发时,有个问题必须先得明确下来,这就是你的插件具体有哪些表现形式,这直接关系到你的框架接口的设计、插件的加载及保存。具体一点,就是说,你的界面上将会出现哪些UI元素,如何进行管理。例如:Combobox、Edit、MenuItem诸如此类的插件。看过一些文章,大都具有子菜单的菜单项和工具栏都当做插件来处理,在本文论及的框架中,没有此类插件,但却同样做到了统一加载,统一管理。

一、命令插件 IAxCommand

接口定义:

public interface IAxCommand : PluginEngine.Interface.IAxPlugin
{

}

这个接口没有任何属性方法,实际上加载到本文框架中的命令插件和工具插件必须分别实现esriSystemUI.ICommand接口和esriSystemUI.ITool接口,这里声明IAxCommand接口只是为了方便插件池对象对所有命令和工具进行管理而已,后面会有所提及。


二、工具插件 IAxTool

接口定义:

public interface IAxTool : PluginEngine.Interface.IAxPlugin
{
IPoint SnappedPoint { get; } //捕捉到的点
}

大家可以发现,这个接口只有一个属性,实际上,在本文框架中,为了改变ArcMap那种只有草图工具可以进行捕捉的尴尬,对于捕捉的环境、捕捉代理的代码全由自己实现,这样一来,对于想要进行捕捉的其他ITool接口实现类,只要同时实现 IAxTool 接口就能进行捕捉了。


三、列表框插件 IAxCombobox

接口定义:

/// 下拉列表插件接口
public interface IAxCombobox : PluginEngine.Interface.IAxPlugin
{
/// 下拉列表的名称
string Name { get; }
/// 下拉列表的标题
string Caption { get; }
/// 是否显示标题
bool ShowCaption { get; }
/// 下拉列表的Items
System.Collections.ICollection Items { get; }
/// 下拉列表的文字
string Text { get; }
/// 下拉列表的类别
string Category { get; }
/// 下拉列表是否可用
bool Enabled { get; }
/// 下拉列表是否可编辑
bool Editable { get; }
/// 下拉列表的宽度
int Width { get; }
/// 下拉列表下拉的最大行数
int DropDownRows { get; }
/// 提示文字
string Tooltip { get; }
/// 出现在状态栏的消息文字
string Message { get; }
/// KeyPress事件
void OnKeyPress();
/// KeyDown事件
void OnKeyDown();
/// EditValueChanged事件
void EditValueChanged(string newText);
/// 列表创建时触发的方法
/// <param name="hook">框架对象</param>
void OnCreate(IAxApplication hook);
}

对于一个下拉列表类型的插件,我们只需要定义上面这些属性和方法、事件差不多就够了,后续章节中,我就针对编辑任务列表这个下拉列表插件做详细介绍。


四、编辑框插件 IAxEdit

接口定义:
public interface IAxEdit : PluginEngine.Interface.IAxPlugin
{
/// 编辑框的名称
string Name { get; }
/// 编辑框的标题
string Caption { get; }
/// 是否显示标题
bool ShowCaption { get; }
/// 编辑框的文字
string Text { get; }
/// 编辑框的类别
string Category { get; }
/// 编辑框是否可用
bool Enabled { get; }
/// 编辑框是否只读
bool ReadOnly { get; }
/// 编辑框的宽度
int Width { get; }
string Tooltip { get; }

///状态栏消息
string Message { get; }
/// KeyPress事件
void OnKeyPress();
/// KeyDown事件
void OnKeyDown();
/// 编辑框创建时触发的方法
/// <param name="hook">框架的对象</param>
void OnCreate(IAxApplication hook);
}

定义这个插件接口,可以显示诸如地图比例尺信息等。


五、菜单组插件 IAxSubItem

接口定义:

public interface IAxSubItem : PluginEngine.Interface.IAxPlugin
{
/// 子菜单的文字
string Caption { get; }
/// 子菜单所属的类别
string Category { get; }
/// 子菜单名称
string Name { get; }
/// 子菜单宽度
int Width { get; }
/// 子菜单产生是触发的方法
/// <param name="hook">框架对象</param>
int Visible { get; } //-1-Never, 0-OnlyInCustomizing, 1-Always

void OnCreate(IAxApplication hook);
}

IAxSubItem这个接口实际上是个容器接口,在最终加载这个插件的时候,寄宿于其之上的其他插件对象都通过XML配置文件有所记录。


六、视图插件 IAxContentsView

接口定义:

public interface IAxContentsView : PluginEngine.Interface.IAxPlugin
{

/// 位图
int Bitmap { get; }
/// 句柄
int hWnd { get; }
/// 名称
string Name { get; }
/// 标题
string Caption { get; }
/// 子控件
System.Windows.Forms.Control ObjecthWnd{ get; }
/// 是否可见
bool Visible { get; set; }
/// 视图的页号
int Index { get; set; }
/// 视图当前选择的对象

object SelectedItem { get; }
/// OnCreate
void OnCreate(IAxApplication hook);
/// Refresh
void Refresh();

------分隔线----------------------------
标签(Tag):Arcgis
------分隔线----------------------------
推荐内容
猜你感兴趣