gis1117
  • 注册日期
  • 发帖数
  • QQ
  • 铜币
  • 威望
  • 贡献值
  • 银元
阅读:818回复:0

如何用Delphi进行ArcObjects的应用开发

楼主#
更多 发布于:2004-04-20 01:58
<P ><b>一、 <FONT face=Arial>ArcObjects</FONT>简介</b></P>
<P >软件重用是业界追求的目标,人们一直希望能够像搭积木一样随意地<FONT face=Arial>“</FONT>装配<FONT face=Arial>”</FONT>应用程序;组件对象就充当了积木的角色。所谓组件对象,实际上就是预先定义好的、能完成一定功能的服务或接口。<FONT face=Arial>Microsoft's Component Object Model </FONT>(组件对象模型,简称<FONT face=Arial>COM</FONT>)是组件对象之间互相接口的规范。凡是遵循<FONT face=Arial>COM</FONT>接口规范的对象彼此之间能相互通信和交互,即使这些对象是由不同的厂商用不同的语言编写,在不同的<FONT face=Arial>Windows</FONT>版本甚至在不同的机器上建立。</P>
<P ><IMG src="http://www.esrichina-bj.cn/library/chinanews/image/new12-delphi1.gif" align=left><FONT face=Arial>ArcObjects</FONT>是<FONT face=Arial>ESRI</FONT>公司提供的一套基于<FONT face=Arial>COM</FONT>技术的组件库。<FONT face=Arial>ArcGIS(tm) </FONT>软件家族中的<FONT face=Arial>ArcMap(tm)</FONT>,<FONT face=Arial>ArcCatalog(tm)</FONT>,<FONT face=Arial>and ArcScene(tm)</FONT>应用程序就是由<FONT face=Arial>ArcObjects</FONT>构建而成的。<FONT face=Arial>COM</FONT>本质上仍然是客户<FONT face=Arial>/</FONT>服务器模式,如<FONT face=Arial>“</FONT>图<FONT face=Arial>A”</FONT>所示,客户(通常是应用程序)请求创建<FONT face=Arial>COM</FONT>对象并通过<FONT face=Arial>COM</FONT>对象的接口操纵<FONT face=Arial>COM</FONT>对象,服务器根据客户的请求创建并管理<FONT face=Arial>COM</FONT>对象。<FONT face=Arial>COM</FONT>是个二进制规范,它与源代码无关,我们可以使用任何支持<FONT face=Arial>COM</FONT>的编程语言(如<FONT face=Arial>Visual Basic</FONT>、<FONT face=Arial>Visual C++</FONT>、<FONT face=Arial>Delpi</FONT>等)做<FONT face=Arial>ArcObjects</FONT>的应用开发。不过,目前的<FONT face=Arial>ArcObjects</FONT>不是独立的<FONT face=Arial>SDK</FONT>,所以要用<FONT face=Arial>ArcObjects</FONT>开发独立的应用系统,必须要在已装有<FONT face=Arial>ArcInfo(tm)</FONT>,<FONT face=Arial>ArcEditor(tm) </FONT>或 <FONT face=Arial>ArcView(tm)</FONT>的环境下进行,以获取软件使用的许可。

二、 <FONT face=Arial>Delphi</FONT>编程环境下<FONT face=Arial>ArcObjects</FONT>的开发过程
由于随机带的<FONT face=Arial>ArcObjects</FONT>开发帮助手册(<FONT face=Arial>ArcObjects Developer Help</FONT>)以及<FONT face=Arial>ESRI
</FONT>公司主页上的<FONT face=Arial>ArcScripts</FONT>里提供的大部分编程指导和例程都是用<FONT face=Arial>Visual Basic</FONT>和<FONT face=Arial>Visual C++</FONT>编写的,为了让习惯于用<FONT face=Arial>Delphi</FONT>工作的程序员们能方便地使用<FONT face=Arial>ArcObjects </FONT>进行独立的应用开发,下面我们用<FONT face=Arial>Delphi 5 + ArcObjects</FONT>来构造一个简单的<FONT face=Arial>GIS</FONT>应用程序作为示例,以供参考。这个应用程序会实现一些如:图形数据的加载,地图的放大、缩小、漫游、全景显示及在地图上添加点状图形标记的功能。
<EM>说明:如过以前已做过第一、二步的工作可以跳过,直接从 第三步入手。</EM>

第一步:引入<FONT face=Arial>ArcObjects </FONT>类型库文件
使用<FONT face=Arial>Delphi 5.0“Project | Import Type Library……”</FONT>菜单项打开<FONT face=Arial>“Import Type Library”</FONT>对话框,从其类型库文件列表框中找到<FONT face=Arial>“ESRI Object Library </FONT>(<FONT face=Arial>Version 1.0</FONT>)<FONT face=Arial>”</FONT>,即为<FONT face=Arial>“%ARCHOME%\bin\esriCore.olb”</FONT>文件。接下来操作需要注意,这时在<FONT face=Arial>“Class Name”</FONT>列表里罗列了所有<FONT face=Arial>esriCore.olb</FONT>实现类的类名,由于其中的部分类名与<FONT face=Arial>Delphi</FONT>的<FONT face=Arial>VCL</FONT>组件库里定义的类名有重复,为了避免产生冲突,建议把上述列表里罗列的所有类名由原来的以<FONT face=Arial>“T”</FONT>开头改为以<FONT face=Arial>“Tesri” </FONT>开头,最后按<FONT face=Arial>“Create Unit”</FONT>,这样在<FONT face=Arial>“Unit dir name”</FONT>编辑栏处指定的目录里会生成一个名为<FONT face=Arial>“esriCore_TLB.pas”</FONT>的该类型库的<FONT face=Arial>Object Pascal</FONT>外套文件,从中可以看出该类型库中的所有<FONT face=Arial>GUID</FONT>常量、类型、接口和<FONT face=Arial>CoClass</FONT>组件类。

第二步:引入<FONT face=Arial>ArcObjects </FONT>地图控件
使用<FONT face=Arial>“Component | Import ActiveX Control……”</FONT>菜单项打开<FONT face=Arial>“Import ActiveX”</FONT>对话框,从其<FONT face=Arial>ActiveX</FONT>控件列表框中找到<FONT face=Arial>“ESRI ArcObjects Controls 8.1</FONT>(<FONT face=Arial>Version1.0</FONT>)<FONT face=Arial>”</FONT>并按<FONT face=Arial>“Install……”</FONT>按钮,然后一路<FONT face=Arial>“</FONT>确认<FONT face=Arial>”</FONT>。这样在<FONT face=Arial>Palette</FONT>控件面板的<FONT face=Arial>ActiveX</FONT>页面上就会出现一个<FONT face=Arial>“TMapControl”</FONT>类型的<FONT face=Arial>ActiveX</FONT>控件。

第三步:功能实现
<FONT face=Arial>1 . </FONT>准备工作
先使用<FONT face=Arial>“File | New Application……”</FONT>菜单项建立一个新的工程,然后选中<FONT face=Arial>Palette</FONT>控件面板的<FONT face=Arial>ActiveX</FONT>页面上<IMG src="http://www.esrichina-bj.cn/library/chinanews/image/new12-Delphi2.gif"> <FONT face=Arial>“MapControl”</FONT>控件,用鼠标拖放到新建工程的窗体上,<FONT face=Arial>MapControl</FONT>的<FONT face=Arial>Name</FONT>属性设为<FONT face=Arial>MapControl</FONT>,<FONT face=Arial>Align</FONT>属性设为<FONT face=Arial>alClient </FONT>,<FONT face=Arial>ShowScrollbars</FONT>属性设为<FONT face=Arial>False</FONT>。最后在<FONT face=Arial>unit1</FONT>单元<FONT face=Arial>interface</FONT>部分的<FONT face=Arial>uses</FONT>字句后添加上对<FONT face=Arial>“esriCore_TLB”</FONT>的引用,这很关键,否则编译器找不到相关的<FONT face=Arial>Interface</FONT>和<FONT face=Arial>CoClass</FONT>的声明。

<FONT face=Arial>2. </FONT>往<FONT face=Arial>MapControl</FONT>控件上加载图层
这里介绍使用的是<FONT face=Arial>shapefile</FONT>格式的数据。给<FONT face=Arial>Form1</FONT>窗体添加一个加载<FONT face=Arial>shapefile</FONT>文件的全局方法<FONT face=Arial>AddShpLayer</FONT>,实现代码如下:
<FONT face=Arial>function TForm1.AddShpLayer(FilePath,FileName: String): String;
var
  pWFactory: IWorkspaceFactory;
  pPropertySet: IPropertySet;
  pWorkspace: IWorkspace;
  pFWorkspace: IFeatureWorkspace;
  pFClass: IFeatureClass;
  pFLayer: IFeatureLayer;
begin
  try
    pWFactory := CoShapefileWorkspaceFactory.Create as IWorkspaceFactory;
    pPropertySet := CoPropertySet.Create as IPropertySet;
    pPropertySet.SetProperty('DATABASE',FilePath);
    pWFactory.Open(pPropertySet,self.Handle,pWorkspace);
    pFWorkspace := pWorkspace as IFeatureWorkspace;
    Delete(FileName,Length(FileName)-3,4);
    pFWorkspace.OpenFeatureClass(FileName,pFClass);
    pFLayer := coFeatureLayer.Create as IFeatureLayer;
    pFLayer.Set_FeatureClass(pFClass);
    pFLayer.Set_Name(FileName);
    MapControl1.AddLayer(pFLayer);
    result := FileName;
  except
   on E: Exception do result := '';
  end;
end;

</FONT>然后在窗体<FONT face=Arial>Form1</FONT>的<FONT face=Arial>OnCreate</FONT>事件里加入以下的代码:
<FONT face=Arial>AddShpLayer('D:\GISData\','STATES.shp')</FONT>;
这时按<FONT face=Arial>F9</FONT>运行程序(此前确保<FONT face=Arial>D:\GISData\STATES.shp</FONT>图层文件存在,即至少包括<FONT face=Arial>D:\GISData\STATES.shp</FONT>、<FONT face=Arial>D:\GISData\STATES.shx</FONT>、<FONT face=Arial>D:\GISData\STATES.dbf</FONT>三个文件),就会发现<FONT face=Arial>STATES</FONT>图层已经加入到了<FONT face=Arial>Mapcontrol</FONT>控件里。

<FONT face=Arial>3. </FONT>地图的放大、缩小、漫游和全景显示
在<FONT face=Arial>Mapcontrol</FONT>控件的<FONT face=Arial>OnMouseDown</FONT>事件里加入以下的代码:
<FONT face=Arial>procedure TForm1.MapControlMouseDown(Sender: TObject; button, shift, x,
  y: Integer; mapX, mapY: Double);
var
  envlp: IEnvelope;
  bIsEmpty: wordbool;
begin
  //</FONT>在<FONT face=Arial>Mapcontrol</FONT>上按下鼠标左键后做拉框操作,实现地图放大功能
<FONT face=Arial>  if (Button = 1) and (Shift = 0) then
  begin
    MapControl.MousePointer := esriPointerZoomIn;
    envlp := MapControl.TrackRectangle;
    envlp.Get_IsEmpty(bIsEmpty);
    if not bIsEmpty then
      MapControl.Extent := envlp
    exit
  end;
  //</FONT>按下<FONT face=Arial>Shift</FONT>键的同时在<FONT face=Arial>Mapcontrol</FONT>上按下鼠标左键在做点击操作,实现地图缩小功能
<FONT face=Arial>  if (Button = 1) and (Shift = 1) then
  begin
    MapControl.MousePointer := esriPointerZoomOut;
    envlp := MapControl.Extent;
    envlp.Expand(2,2,False);
    MapControl.Extent := envlp;
    exit;
  end;
  //</FONT>在<FONT face=Arial>Mapcontrol</FONT>上按下鼠标右键键后做拖动操作,实现地图漫游功能
<FONT face=Arial>  if (Button = 2) and (Shift = 0) then
  begin
    MapControl.MousePointer := esriPointerPanning;
    MapControl.Pan;
    MapControl.MousePointer := esriPointerPan;
    exit;
  end;
end;

</FONT>在<FONT face=Arial>Mapcontrol</FONT>控件的<FONT face=Arial>OnDoubleClick</FONT>事件里加入以下的代码:
<FONT face=Arial>procedure TForm1.MapControl1DoubleClick(Sender: TObject; button, shift, x,
  y: Integer; mapX, mapY: Double);
begin
    // </FONT>在<FONT face=Arial>Mapcontrol</FONT>上双击,实现地图全景显示功能
<FONT face=Arial>    MapControl1.Extent := MapControl1.FullExtent;
end;

4. </FONT>地图上添加点状图形标记的功能
先声明两个窗体<FONT face=Arial>Form1</FONT>的私有变量:
<FONT face=Arial>    F_MultiPoint: IMultiPoint;
    F_Pts: IPointCollection;
</FONT>再在窗体<FONT face=Arial>Form1</FONT>的<FONT face=Arial>OnCreate</FONT>事件里加入以下的代码:
<FONT face=Arial>    F_MultiPoint := CoMultiPoint.Create as IMultiPoint;
    F_Pts := F_MultiPoint as IPointCollection;
</FONT>然后给<FONT face=Arial>Form1</FONT>窗体添加一个的用于添加点状图形标记的全局的方法<FONT face=Arial>DrawPoint</FONT>,
实现代码如下:
<FONT face=Arial>procedure TForm1.DrawPoint;
var
  pt_cnt,i: integer;
  sym: ICharacterMarkerSymbol;
  pt: IPoint;
  ft: TFont;
  oleft: variant;
  ScreenDisplay: IScreenDisplay;
ActiveView: IActiveView;
begin
  ActiveView := MapControl.ActiveView;
  ActiveView.Get_ScreenDisplay(ScreenDisplay);
  F_Pts.Get_PointCount(pt_cnt);
  if pt_cnt > 0 then
  begin
    ScreenDisplay.StartDrawing(0,0);
    for i := 0 to pt_cnt-1 do
    begin
      F_Pts.Get_Point(i,pt);
      sym := coCharacterMarkerSymbol.Create as ICharacterMarkerSymbol;
      sym.Set_Size(30);
      ft := TFont.Create;
      ft.Size := 40;
      ft.Name := 'Wingdings';
      oleft := FontToOleFont(ft);
      sym.Set_Font(IFontDisp(IDispatch(oleft)));
      sym.Set_CharacterIndex(i+33);
      ScreenDisplay.SetSymbol(sym as ISymbol);
      ScreenDisplay.DrawPoint(pt);
    end;
    ScreenDisplay.FinishDrawing;
  end;
end;

</FONT>然后在<FONT face=Arial>Mapcontrol</FONT>控件的<FONT face=Arial>OnMouseDown</FONT>事件里加入以下的代码:
<FONT face=Arial>  //</FONT>按下<FONT face=Arial>Shift</FONT>键的同时在<FONT face=Arial>Mapcontrol</FONT>上按下鼠标右键在做点击操作,
<FONT face=Arial>  //</FONT>实现在地图上添加点状图形标记的功能
<FONT face=Arial>  if (Button = 2) and (Shift = 1) then
  begin
    pt := mapcontrol1.ToMapPoint(x,y);
    F_Pts.AddPoint(pt,EmptyParam,EmptyParam);
    DrawPoint;
    exit;
  end;
</FONT>最后,在<FONT face=Arial>Mapcontrol</FONT>控件的<FONT face=Arial>OnAfterDraw</FONT>事件里加入以下的代码:
<FONT face=Arial>  procedure TForm1.MapControlAfterDraw(Sender: TObject; const
    display: IDisplay; phase: TOleEnum);
  begin
    DrawPoint; //</FONT>用于刷新添加在地图上的点状图形标
<FONT face=Arial>  end;
</FONT>这样,一个包含了一些简单的<FONT face=Arial>GIS</FONT>功能的应用程序就完成了(按<FONT face=Arial>F9</FONT>可以运行)。

三、 结束语
希望以上的这个小例程能给习惯于用<FONT face=Arial>Delphi</FONT>工作的<FONT face=Arial>ArcObjects</FONT>程序开发者一点启发,从而开发出各种强大的<FONT face=Arial>GIS</FONT>应用系统来。</P>
喜欢0 评分0
游客

返回顶部