Delphi+ArcEngine开发手记 一

项目需求之一:精简汉化版的ArcMap:)

平台:DelphiXE+AE9.3

一.小技巧 :a.Delphi的Tool中加入两个非常有用的工具Library locator/EO Browser,这两个工具用来解决Arc编程中单元引用、类型强制转换接口问题,可以大大提高效率;b. Delphi Options的Type Library中勾选 All v-table Interfaces,访问ActiveX的属性与方法时,就可以避免使用Get/Set的繁琐。

二.设计与问题

1.没有选用C#的主要原因在于针对SDK(ActiveX)的开发中,换一台开发机器,源代码运行经常会出现”初始值设定问题“、”初始化控件问题“、”类没有注册问题“ ,据一哥们儿反映说是要在新机器上重新搭建界面就会OK,个人没有测试。另一方面原因也在于桌面开发中C#的开发效率、IDE的运行效率确实无法同Delphi相比,顺便鄙视一下那些没有用过这两种语言而胡乱叫唤这个好那个坏的半瓶醋。平台无好坏之分,用其所长才算王道,达人先贤们早说过的至理明言,不多啰嗦。另外,这个项目需求中还存在数据同步、文件同步(其解决方案后面会记录下来),带源码的Indy/改良后的DataSnap,也让我没有抑制住DelphiXE的诱惑。

2. 界面:Ribbon;三方组件:Dev/VclZip(数据同步、自动升级中的打包);

3. 编程思路:大部分ArcMap功能由ICommand完成,小部分功能,如自定义符号、增加图层、标注要点等要化繁为简,手工代码完成;特殊功能:鹰眼,手工完成。

4.问题:a.ICommand的调用 所有AE中的命令分为两类,一种是Command类型的,一种是Tool类型的,两种命令的执行均需要Hook到MapControl上、OnClick或设置为MapControl的当前工具(正在用的),请看代码:

工具类的

var cmd:ICommand;

begin

cmd:=CoControlsMapPanTool.Create as ICommand;

cmd.OnCreate(mapControl2.ControlInterface);

mapControl2.ControlInterface.CurrentTool:=ITool(cmd);

end;

命令类的:

var cmd:ICommand;

begin

cmd:= CoControlsClearSelectionCommand.Create as ICommand;

cmd.OnCreate(mapControl2.ControlInterface);

cmd.OnClick;

end;

不知道是命令还是工具的,也好办,导入ActiveX时,足足有上百个(没有细数),几乎每个命令在面板上都是一个组件,有心的可以看出尾巴上是Tool还是Command,就可以进行区分了。

有了这种调用方式,从漫游开始,所有的在工具栏、菜单栏里的命令几乎可以全部搞定。

b.地图文件的操作

打开、另存工具栏命令中就有,居然没有保存?总不会让我去另存一个已经打开经过编辑的地图罢。网上搜搜,某位老师使用MapDocument对象来解决打开、保存、另存。且看代码(我改出的Delphi,源代码为VB) :

Private

MapDoc:IMapDocument;//维持一个私有对象

在窗体创建时加入以下代码:

mapDoc:=coMapDocument.Create as IMapDocument;

打开文件(MXD)

//var

// i: Integer;

//begin

// if dlgOpen1.Execute then

// begin

// mapDoc.Open(dlgOpen1.FileName,'');

// Cursor:=crHourGlass;

//// for i := 0 to mapDoc.MapCount-1 do

//// begin

//// mapCtl1.DefaultInterface.Map:=mapDoc.Map[i];

//// end;

// mapCtl1.Update;

// Cursor:=crDefault;

// end;

//end;

另存

// if dlgSave1.Execute then

// begin

// mapDoc.SaveAs(dlgSave1.FileName,True,True);

// end;

注意:mapCtl1.DefaultInterface几乎包含了所有C#中用到的属性和方法,在MapControl中无法调用的,可以到DefaultInterfase,如上例中的IMap对象

到这一步,虽然可以解决Save问题,可是执行效率也太低了,打开一幅图的时候比人家ArcMap差好多倍,没有,只好到C#中的ArcGis项目中寻求答案:

Esri是这样做的,除了Save以外,其余的以ICommand来实现。

”偷师“的C#源码

IMapDocument mapDoc = new MapDocumentClass();

mapDoc.Open(m_mapDocumentName, string.Empty);

//Make sure that the MapDocument is not readonly

if (mapDoc.get_IsReadOnly(m_mapDocumentName))

{

MessageBox.Show("Map document is read only!");

mapDoc.Close();

return;

}

//Replace its contents with the current map

mapDoc.ReplaceContents((IMxdContents)m_mapControl.Map);

//save the MapDocument in order to persist it

mapDoc.Save(mapDoc.UsesRelativePaths, false);

//close the MapDocument

mapDoc.Close();

}

至此,ArcMap中的常用功能基本开发完毕。下篇手记中,上来几张所开发系统的图片