|
阅读:818回复:0
如何用Delphi进行ArcObjects的应用开发
<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> |
|