Delphi+ArcEngine开发手记 二

接上文继续:)

Delphi的保存地图代码:

var mapDoc:IMapDocument;//把在Private定义的MyDoc去掉

begin

mapDoc:=coMapDocument.Create as IMapDocument;

mapDoc.Open(mapCtl1.DocumentFilename,'');

if mapDoc.IsReadOnly[mapCtl1.DocumentFilename] = False then

begin

mapDoc.ReplaceContents(mapCtl1.Map as IMxdContents);

mapDoc.Save(mapDoc.UsesRelativePaths, false);

//close the MapDocument

mapDoc.Close();

end

else

Application.MessageBox('文件只读,保存失败!','警告');

end;

由于Delphi代码编辑器的设定,软回车在这里会失去作用。看者留心即可。

这里重点说明一下,网上有很多版本讲还需要拷贝一个MapControl中的副本,否则会有一些元素存储不上,我还没有试过这些。如果确实如此,后文将会提到。

一个精简版的ArcMap首重的应该是在现有地图上进行一些特殊的标记或定制,我做的这个项目也不例外。因此,费了很大气力,研究了手册(三个:ArcCatalog、ArcMap的操作、制作),整理了一下编程步骤:添加特定图层、制作自定义符号、标注。

添加图层:涉及的类很多,有很多类看着脑袋都大,但是条理还是蛮清楚的。废话少说,先上代码。

我是先创建了Shape格式文件,尔后加载到打开的地图上。

procedure CreateShpFile(Dir{文件夹},FileName{文件名}:string;SpatialRefer:ISpatialReference{坐标投影});

var aWorkSpaceFactory:IWorkspaceFactory;

aFeatureWorkSpace:IFeatureWorkspace;

aFields:IFields;

aFieldsEdt:IFieldsEdit;

aField:IField;

aFieldEdt:IFieldEdit;

aGeoDef:IGeometryDef;

aGeoDefEdt:IGeometryDefEdit;

aUnknownCSys:IUnknownCoordinateSystem;

begin

if FileExists(dir+FileName) then

DeleteFile(dir+FileName);

aWorkSpaceFactory:=coShapefileWorkspaceFactory.Create as IWorkspaceFactory;

aFeatureWorkSpace := aWorkSpaceFactory.OpenFromFile(Dir,0) as IFeatureWorkspace;

aFields:=coFields.Create as IFields;

aFieldsEdt:= aFields as IFieldsEdit;

aField:=CoField.Create as IField;

aFieldEdt:= aField as IFieldEdit;

aFieldEdt.Name:= 'Shape';

aFieldEdt.type_:=esriFieldTypeGeometry;

aGeoDef:=coGeometryDef.Create as IGeometryDef;

aGeoDefEdt:= aGeoDef as IGeometryDefEdit;

aGeoDefEdt.GeometryType:= esriGeometryPoint;

//

aGeoDefEdt._Set_SpatialReference(SpatialRefer);

// aUnknownCSys:=CoUnknownCoordinateSystem.Create as IUnknownCoordinateSystem;

// aGeoDefEdt._Set_SpatialReference(aUnknownCSys);

//略去一函数CreateSpatialReference;用户可以使用此函数定制属于自己的空间参照系

aFieldEdt._Set_GeometryDef(aGeoDef);

aFieldsEdt.AddField(aField);

aFeatureWorkSpace.CreateFeatureClass(FileName,aFields,nil,nil,esriFTSimple,'Shape','');

end;

上述代码,估计用过AE的都能看得懂,如果存在跟我一样的老菜鸟,那就听听俄滴理解罢。

建工厂(WorkSpaceFactory)=》开车间(WorkSpace)=>进设备(Fields/Field/GeometryDef)=>产品定位(SpatialReference)=》开工生产(Create)

鉴于我前面写的,是在现有地图的情况下进行的定制,这里也不玩其它参数了,所以调用时就采用现有的空间参数:

var

dir: string;

fn: string;

begin

dir:=ExtractFilePath(mapCtl1.DocumentFilename);

fn:='Test.shp';

CreateShpFile(dir,fn,mapCtl1.DefaultInterface.SpatialReference);

mapCtl1.DefaultInterface.AddShapeFile(dir,fn); //mapCtl1就是MapControl

有兴趣的同志可以到Esri中国社区查一下如何定义空间参数。

开发至此,有几个Delphi开发AE的心得:

1.变量设定基本上是接口:ILayer/ICommand/IWorkSpaceFactory/IField....

创建时 全部使用co打头的类上阵,以As转换

2.某个接口泛红了,或者是前人写的代码编译不过去的话,基本上是没有引用相应单元的结果,使用Library Locator找到它家,在uses里面加上即可。

3.以As进行强制转换时,如果报这样那样的错误,通常是转换类型不允许,使用EO Browser工具查找到相应的类,看看支持的接口,再排错。

4.要善于使用MapControl的DefaultInterface接口,所有其它语言支持而Delphi中不含的属性,加上这个接口试试罢。

5.在Delphi还有一个常遇到的问题,也是和其它语言区别最大的地方,就是好多其它语言支持直接赋值的属性到了Delphi中变成了Read-Only,如MapControl中的Map,GeometryDefEdit的SpatialReference等等,解决方法就是先找找有无_Set之类的方法,象上面代码中的。再者就是看看有没有衍生出来的接口,象DefaultInterface之类的。如果找到,恭喜你:)抱着石头又过了一条小溪。

今天就到这里罢。欢迎用Delphi开发的同志们一起来补充一些技巧,充实人生,乐趣无限。