ArcObjects SDK 006 ICommand和ITool接口
ICommand接口是插件协议之一,继承该接口的类都可以成为命令。即点击一下执行,不主动与宿主发生鼠标和键盘交互。该接口包含的重要成员如下表所示。
序号 |
名称 |
类型 |
描述 |
1 |
Bitmap |
Int |
命令上显示的图标 |
2 |
Caption |
String |
命令上显示的文字 |
3 |
Checked |
Bool |
命令是否处于选中状态 |
4 |
Enabled |
Bool |
命令当前是否可用 |
5 |
OnClick |
函数 |
点击命令时,触发执行的函数 |
6 |
OnCreate |
函数 |
创建该命令时,调用的函数 |
7 |
Tooltip |
String |
鼠标放到命令上要显示的文字 |
这些属性和函数的名字都比较容易理解,一看就知道其作用。如果我们自己继承ICommand实现一个弹出当前地图包含几个图层的命令,命名为LayerCountCommand。那么只要在OnClick函数中,获取OnCreate函数传进来的宿主对象,从宿主对象中获取当前加载的地图,进而获取其包含的几个图层,使用消息对话框弹出即可。
我们实现命令时候,只需要关注宿主对象就可以了,和其他Command不会发生直接关联。如果需要和其他Command关联,那么这些关联都通过宿主进行。例如我们刚才实现的LayerCountCommand在地图图层为0的时候,其处于不可用的状态,也就是 Enabled属性等于False。按照正常思维的话,我们会在OpenMapCommand里面,判断一下当前图层个数是否为0,从而设置设置LayerCountCommand实例的Enabled属性。那RemoveLayerCommand、AddLayerCommand、NewMapCommand等怎么办呢?难道每个命令里面都要判断LayerCountCommand是都可用?
当然不会是这样,我们会为宿主添加MapChanged和LayersChanged事件,无论用OpenMapCommand还是其他地方,在系统中打开一个新地图后,宿主对象就会触发MapChanged事件。而我们实现的LayerCountCommand会监测该事件,当该事件触发后,LayerCountCommand会判断当前地图有几个图层,从而设置自己是否是可用。
这样LayerCountCommand只关系宿主的信息,间接的和OpenMapCommand产生了关联。而LayerCountCommand自己可以决定自己是否可用,这就形成了高内聚,低耦合的设计。
ITool接口也是插件协议之一,实现该接口的类我们成为工具,这些工具是可以和地图显示控件进行鼠标、键盘交互的。该接口包含的重要成员如下表所示。
序号 |
名称 |
类型 |
描述 |
1 |
Cursor |
Int |
鼠标在地图显示控件上的样式 |
2 |
Deactivate |
函数 |
工具失活的时候触发的函数 |
3 |
OnMouseDown |
函数 |
鼠标按下执行的函数 |
4 |
OnMouseMove |
函数 |
鼠标移动执行的函数 |
5 |
OnMouseUp |
函数 |
鼠标弹起执行的函数 |
6 |
OnDblClick |
函数 |
鼠标双击地图显示控件执行的函数 |
7 |
OnKeyDown |
函数 |
键盘按键按下执行的函数 |
8 |
OnKeyUp |
函数 |
键盘按键弹起执行的函数 |
每个宿主对象都有CurrentTool属性,如果点击MapZoomInTool工具,那么该宿主的CurrentTool就是该工具了。当鼠标在宿主对象上按下的时候,会自动调用宿主对象CurrentTool属性值的OnMouseDown,也就是MapZoomInTool工具的OnMouseDown函数。当鼠标在宿主对象上移动的时候,会自动调用MapZoomInTool的OnMouseMove函数。其他动作一次类推,并且宿主对象读取CurrentTool的Cursor作为当前的鼠标样式。
要做一个放大工具,需要考虑拉框放大、点击放大等。但有了宿主程序,就可以把这些代码完整的封装到MapZoomInTool类中。而实现地图缩小功能MapZoomOutTool以及地图平移的MapPanTool,完全不需要知道其他工具的存在,也不关心其他Tool都做了什么。
在ArcMap中,地图放大、地图缩小、地图平移、地图全图地图即放大、地方即缩小、上一视图和下一视图这几个Tool和Command关系非常密切。如下图所示。
但通过这种插件式架构,他们不光代码之间无直接联系,而且还可以做到随意组合使用。例如我们开发的系统可以使用放大、缩小和平移三个工具,也可以加上全图,或者再加上其他工具,都可以正常运行。这种模式非常值得我们思考和借鉴。
3、ArcObjects SDK已经实现了哪些Command和Tool
AO中实现了二三百个命令和工具,我们常用的大概有几十个。可以在帮助中通过查看ICommand接口,查看到底有哪些实现。
也可以通过ArcMap查找,出现在ArcMap工具条上的按钮,大部分都能在此找到对应的类。
ArcMap就是通过这种插件式架构把各种Command和Tool组合起来的,而这些Comamnd和Tool的背后是一个个功能点。不光使得ArcMap可以持续集成那么多功能,甚至可以开放接口,让开发人员直接在ArcMap上扩展。
那这种模式是不是可以借鉴到我们的软件开发中?答案是肯定的,下面我们就来设计自己的App-Command框架。