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开发的同志们一起来补充一些技巧,充实人生,乐趣无限。 

 

posted @ 2011-03-22 23:42  wolf1860  阅读(1613)  评论(0编辑  收藏  举报