




已阅读5页,还剩10页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
MapObjects 2.2在Visual Studio.Net环境里的开发MapObjects 2.2 SDK for .NET简介虽然.NET应用程序不能直接使用ActiveX控件,但是.NET框架提供的与COM协同工作的能力可以让我们在.NET项目当中无缝地利用ActiveX控件。ESRI为MapObjects 2.2 ActiveX控件提供了运行环境可调用包装(RCW),让我们可以在.NET的项目中创建、调用MapObjects的Map控件和其他对象的方法。MapObjects库里的每一个COM类都由一个RCW类在扮演。举个例子,RCW类MapLayerClass包装了COM类MapLayer。每一个RCW类都包含了所有能从对应的COM类访问到的公有成员。MapObjects 2.2的RCW属于ESRI.MapObjects 2.Core名称空间,它定义在名为ESRI.MapObjects 2.Core.dll和ESRI.MapObjects 2.Control.dll的两个互操作层组合体。除了这两个主要的,另外还有两个支持对MapObjects软件进行扩展的互操作层组合体,ESRI.MapObjects 2.Custom.dll和ESRI.MapObjects 2.MemTable.dll。前者包含了用户定制自己的图符、渲染方式和投影方式的定义,后者包含了MapObject2.1发布时推出的内存表(MemTable)功能的扩展库。另外名称空间里也包含了以原始的类的名字来命名的接口。举个例子,RCW类MapLayerClass就实现了一个名为MapLayer的接口。这个接口暴露了所有从原始的类可直接获得的成员,所以不管是接口还是原始的类都可被用来调用COM对象的成员。不过从ESRI的文档来看,更习惯于使用接口。VB.NETDim pnt As ESRI.MapObjects2.Core.Point = NewESRI.MapObjects2.Core.PointClass()C#ESRI.MapObjects2.Core.Point pnt = newESRI.MapObjects2.Core.PointClass();另外,需要记住的是,在使用这些包装类的同时,其实仍然在访问MapObjects 2.2的ActiveX控件,所以不管是你用于开发的机器,还是今后部署了你的应用的机器,仍然需要安装MapObjects 2.2产品,当然后者一般建议安装MapObjects 2.2的运行时安装包。MapObjects 2.2在Visual Studio .Net环境里的开发实例现在,我们将在Visual Studio.NET环境里构造一个简单的电子地图的应用。它可以增加一个图层,实现地图的放大、漫游和全景显示,并且可以实现要素的定位功能。第一步:创建一个新的窗口应用打开Visual Studio.NET,点击主文档窗口里Start Page上的New Project按钮或菜单条上File菜单项里的New的子项Project,会弹出一个窗口(图1),在窗口的左手边我们可以选择是创建一个Visual Basic(.NET)的工程还是Visual C#的工程。选定了工程类别,在右手边选择Windows Application图标,并在Name文字输入行内输入当前工程的名称,如GettingStarted,最后按OK按钮确定。此时主文档窗口里就生成了一个设计状态下的空白窗体。第二步:加入MapObjects 2.2的ActiveX控件先点击Tools菜单的Customize ToolBox菜单子项,会弹出一个窗口,在窗口的.NET Framework Components标签页上,选中多选框内名为AxMap的子项,然后按OK按钮确定。以上的操作如果以前做过,这里可以不用再重复。从浮动在主文档窗口左侧的ToolBox窗口里找到AxMap按钮并双击它,这时一个AxMap控件就加到前面创建的窗体上了。第三步:电子地图功能的实现(这里以Visual Basic.NET的工程为例)为了程序书写的方便,在代码窗口的头上加上ImportsESRI.MapObjects2.Core语句,这样做的好处可以举个例子说明,没有这行语句的时候,我们要声明一个Symbol接口类型的变量必须很完整的写成Dim sym AsESRI.MapObjects2.Core.Symbol,若是添加了这行语句,以上的变量声明只需写成Dim sym As Symbol就行了。接下来开始实现具体的功能。1给地图控件加载图层这里以加载shapefile格式的数据为例,先创建一个全局的方法AddShpFile,实现如下:PublicSub AddShpFile(ByVal FilePathAsString,ByVal FileNameAsString)Dim dcAsNew DataConnection()dc.Database() = FilePathIf dc.Connect ThenDim lyrAsNew MapLayer()lyr.GeoDataset = dc.FindGeoDataset(FileName)AxMap1.Layers.Add(lyr)ElseMsgBox(No such a file exists)End IfEnd Sub然后在窗体上添加一个Button控件,并在它的Click事件里调用AddShpFile方法:PrivateSub Button1_Click(ByVal senderAs System.Object, _ByVal eAs System.EventArgs)Handles Button1.ClickDim FilePathAsString = D:ESRIMapObjects2.2SamplesDataWorldDim FileNameAsString = country.shp以上两行根据实际情况进行适当修改AddShpFile(FilePath, FileName)End Sub此时按F5键运行程序,点击窗口上的Button1按钮,一幅世界地图就加载上来了。2 地图的放大、漫游和全景显示在AxMap控件的MouseDownEvent事件里加入实现地图的放大和漫游的代码,如下:PrivateSub AxMap1_MouseDownEvent(ByVal senderAsObject, _ByVal eAs ESRI.MapObjects2.Core.MouseDownEventArgs)Handles AxMap1.MouseDownEventIf e.button = 1 Then在AxMap控件上按下鼠标左键后做拉框操作,实现地图放大功能Dim pRectAs RectanglepRect =Me.AxMap1.TrackRectangleIfNot pRectIsNothing ThenMe.AxMap1.MousePointer = MousePointerConstants.moZoomInMe.AxMap1.Extent = pRectEnd IfElse在AxMap控件上按下鼠标右键键后做拖动操作,实现地图漫游功能Me.AxMap1.MousePointer = MousePointerConstants.moPanningMe.AxMap1.Pan()Me.AxMap1.MousePointer = MousePointerConstants.moPanEnd IfEnd Sub在AxMap控件的DblClick事件里加入实现地图全景显示的代码,如下:PrivateSub AxMap1_DblClick(ByVal senderAsObject, _ByVal eAs System.EventArgs)Handles AxMap1.DblClick在AxMap控件上双击,实现地图全景显示功能AxMap1.Extent = AxMap1.FullExtentEnd Sub3 地图要素定位在窗体上添加一个TextBox控件,在它的KeyDown事件里加入实现地图要素定位的代码,如下:PrivateSub TextBox1_KeyDown(ByVal senderAsObject, _ByVal eAs System.Windows.Forms.KeyEventArgs)Handles TextBox1.KeyDownIf e.KeyCode = Keys.Return ThenDim expAsString = NAME = + TextBox1.Text + Dim lyrAs MapLayer =Me.AxMap1.Layers.Item(0)Dim recsAs Recordset = lyr.SearchExpression(exp)IfNot recs.EOF ThenDim resAs Polygon = recs.Fields.Item(Shape).ValueDim extAs Rectangle = res.Extentext.ScaleRectangle(2.0)Me.AxMap1.Extent = extMe.AxMap1.CtlRefresh()Me.AxMap1.FlashShape(res, 3)End IfEnd IfEnd Sub此时按F5键运行程序,点击窗口上的Button1按钮加载世界地图,然后在TextBox文字输入行里输入想要查询的国家的名称,比如China,最后按回车键确定,China就会显示到地图的中央,并高亮闪烁三次,如图2。到这里,一个简单的电子地图的应用程序就完成了。有过在VB、VC或Delphi环境里开发MapObjects的GIS工作者可能会发现,了解了.NET的工作机制之后,在.NET环境里开发MapObjects 2.2的应用并不会有太多的困难。尽管如此,还是有几个问题是需要我们注意的。1.MapObjects的Refresh方法与AxHost的Refresh方法的比较.NET框架提供了一个名叫AxHost的类,它是一种控件。凡是以AxHost为基类继承而来的类都可以置于Windows的窗口上。ActiveX控件在.NET里的应用就是通过利用AxHost类来实现的。MapObjects 2.2中的AxMap类就是从AxHost类继承而来的,所以它能置于Windows的窗口之上,当然它包含了对潜在的ActiveX控件Map的引用。可是,AxHost也有一个名叫Refresh的方法,这刚好与MapObjects 2.2的ActiveX控件Map的一个方法同名。所以当在调用AxMap.Refresh方法的时候,其实是在调用从AxHost继承下来的方法。而MapObjects自己的Refresh方法已被改名为CtlRefresh,为了实现刷新地图的功能,现在要改用CtlRefresh,也就是AxMap.CtlRefresh。事实上,像这样在ActiveX控件的同名成员之前加上“Ctl”的前缀是一种标准的协定。2.数据类型匹配C#语言本身对数据类型的检查就很严格,我们常常需要通过显式的类型转换来满足它的要求。尽管从语法来讲在VB.NET环境里这方面的工作我们可以做得比较“模糊”,但事实上,如果在工程里做了相应的设置,VB.NET对同样的问题也会变得很“斤斤计较”。所以为了程序在编译时和运行时更少地出现错误,必须规范这方面的工作。举个例子,应该是:C#ESRI.MapObjects2.Core.MapLayer lyr = (ESRI.MapObjects2.Core.MapLayer) axMap1.Layers.Item(0);VisualBasicDim lyr As ESRI.MapObjects2.Core.MapLayer = CType(AxMap1.Layers.Item(0), ESRI.MapObjects2.Core.MapLayer)而不是:C#ESRI.MapObjects2.Core.MapLayer lyr = axMap1.Layers.Item(0);VB.NETDim lyr As ESRI.MapObjects2.Core.MapLayer = AxMap1.Layers.Item(0)关于类型匹配还有一个很典型的例子就是MapObjects 中Color的使用。MapObjects 中的Color是OLE_COLOR类型的,应用在.NET里它等同于无符号的32位整数行(UINT32),所以要做必要的类型转换,尽管转换是非常方便的:C#ESRI.MapObjects2.Core.Symbol sym = new ESRI.MapObjects2.Core.SymbolClass();sym.Color = Convert.ToUInt32(ESRI.MapObjects2.Core.ColorConstants.moRed);VB.NETDim sym As ESRI.MapObjects2.Core.Symbol = New ESRI.MapObjects2.Core.Symbol()sym.Color = Convert.ToUInt32(ESRI.MapObjects2.Core.ColorConstants.moRed)3. 常数的使用.NET为MapObjects 2.2的常数枚举类型都作了包装,它们都是从System.Enum类继承下来的。在代码中使用这些常数时必须使用完整的枚举名称来限定所用的常数。C#ESRI.MapObjects2.Core.Symbol sym = new ESRI.MapObjects2.Core.SymbolClass();sym.SymbolType = ESRI.MapObjects2.Core.SymbolTypeConstants.moFillSymbol;VisualBasicDim sym As ESRI.MapObjects2.Core.Symbol = New ESRI.MapObjects2.Core.SymbolClass()sym.SymbolType = ESRI.MapObjects2.Core.SymbolTypeConstants.moFillSymbol(王嘉彬) .NET环境下MapObjects编程存在的问题及解决方法蔡德利(黑龙江八一农垦大学植物科技学院,大庆 163319)摘要:本文对.NET环境下使用MapObjects控件开发GIS应用程序遇到的数据类型、右键上下文菜单、几何对象序列化等问题作了讨论,分析了原因,并提出了较好的解决方法,对.NET环境下GIS的开发具有指导作用。关键字:.NET;MapObjects;几何对象;序列化The Problems and Solutions Programming with MapObjects in .NET EnvironmentCai Deli(College of Plant Sciences and Technology, Heilongjiang August First Land Reclamation University, Daqing 163319)Abstract:The problems of Data Types, Shortcuts Menu, Geometry Objects Serialization that we found in the course of development for GIS application with MapObjects ActiveX control were discussed in this paper. The causes were analyzed and the solutions were put forward. All this will give directions in GIS development in .NET environment.Keyword:.NET;MapObjects;Geometry Objects;Serialization0 引言 MapObjects 2.2是美国ESRI的GIS二次开发AxtiveX控件,.NET Framework提供的与COM互操作技术(COM Interop)允许对现有的COM组件进行访问而无须修改原组件,所以ESRI为MapObject 2.2提供了运行环境可调用包装(RCW),让我们可以在.NET项目中使用MapObjects的Map控件及相关对象。 .NET开发环境是一套向下兼容的应用程序开发工具,尽管编程技术与以前变化不大,但一些功能的增强和语言上的差异导致MapObjects在.NET项目开发时存在着较多的问题,下面就针对它们讨论相应的解决方法。1 数据类型 数据类型用来声明编程元素的取值范围和存储方式。在默认情况下,Visual Basic编译器要求每个局部变量在使用之前必须声明,虽声明但无数据类型的变量都具有Object数据类型。如果用Object声明变量,则变量只能使用Object类的成员。而用特定的类声明变量时,变量可以访问由该类公开的所有方法和属性。 在MapObjects中进行数据访问,使用如下语句移动数据指针: myLayer.Records.MoveFirst() myLayer.Records.MoveNext()此时Recordset中的数据指针并不移动,应将程序改为: Dim myRecs as ESRI.MapObjects2.Core.Recordset myRecs = myLayer.Records 或myRecs = Ctype(myLayer.Records, ESRI.MapObjects2.Core.Recordset) myRecs.MoveFirst() myRecs.MoveNext() 在访问图层时也存在同样的问题,如果直接访问图层: Map1.Layers.Item(0).records.NET会认为Records是Object类型,而并不是Recordset类型,所以应写作: Dim myLayer As ESRI.MapObjects2.Core.MapLayer myLayer = Ctype(Map1.Layers.Item(0), ESRI.MapObjects2.Core.MapLayer) Dim myRecs as ESRI.MapObjects2.Core.Recordset myRecs = Ctype(myLayer.Records, ESRI.MapObjects2.Core.Recordset) MapObjects中的Color是OLE_COLOR类型的,在.NET中相当于无符号整数(System.UInt32),而无符号整数并不是Visual Basic.NET提供的数据类型,所以不受VB.NET支持。因此,要利用System命名空间的Convert类将一个基本数据类型转换为另一个基本数据类型,程序如下: Dim sym As New ESRI.MapObjects2.Core.Symbol sym.Color = Convert.ToUInt32(ESRI.MapObjects2.Core.ColorConstants.moRed)2 右键菜单图1 Map控件加入到TabControl控件中实现右键菜单 Windows应用程序右键上下文菜单是非常有效的操作方式,在.NET下实现右键菜单很简单。Control类具有ContextMenu属性,其派生类也具有ContextMenu属性,在应用程序中只需创建一个ContextMenu对象,并赋于相应对象的ContextMenu属性就可以了。但MapObjects的Map控件却没有ContextMenu属性。 解决这个问题的方法是,将Map控件放到一个容器控件中,设置Map控件的Dock属性为Fill,使两者合为一个整体。然后,将建立的ContextMenu对象赋于容器控件的ContextMenu属性。 .NET提供的容器控件主要有Panel、TabControl和GroupBox。在TabControl中实现上下文菜单的效果如图1所示。3 几何对象的序列化 .NET中的序列化是将对象状态转变为可保持或传输的格式的过程,与其相反的操作是反序列化。序列化包括二进制序列化和XML序列化两种技术。 通常一个类包含非托管的内存或文件句柄时,是不支持序列化的。COM组件、AxtiveX接口和Win32 API函数都是非托管代码,因此,MapObjects的几何对象均不支持序列化操作,无法直接转变为二进制或XML数据,从而进行远程传输。 对MapObjects的Polygon对象进行考察发现,Polygon对象由一个Parts对象构成,Parts中的每个Part对象都是Points对象,Points对象中有若干个Point对象,当不包含Z值时,Point对象的(x,y)是Polygon对象的一个拐点。 因此,可以编写以下程序将一个Polygon转变为二进制数据: Public Function ConvertPolygonToByte(ByVal oPoly As ESRI.MapObjects2.Core.Polygon) As Byte() Dim bytCount(2), bytData(8), bytPoly() As Byte Dim intByteCount As Integer = 0 Dim shtPartCount As Short = oPoly.Parts.Count 部件数 Dim dblXY As Double, i As Short bytCount = BitConverter.GetBytes(shtPartCount) 转换部件数为byte() ReDim Preserve bytPoly(intByteCount + 2) Array.Copy(bytCount, 0, bytPoly, intByteCount, 2) intByteCount +=2 For i = 0 To shtPartCount - 1 Dim oPart As ESRI.MapObjects2.Core.Points = oPoly.Parts.Item(i) Dim shtPointCount As Short = oPart.Count 点数 bytCount = BitConverter.GetBytes(shtPointCount) 转换点数为byte() ReDim Preserve bytPoly(intByteCount + 2) Array.Copy(bytCount, 0, bytPoly, intByteCount, 2) intByteCount +=2 Dim j As Short For j = 0 To shtPointCount - 1 Dim oPoint As ESRI.MapObjects2.Core.Point = oPart.Item(j) dblXY = oPoint.X bytData = BitConverter.GetBytes(dblXY) ReDim Preserve bytPoly(intByteCount + 8) Array.Copy(bytData, 0, bytPoly, intByteCount, 8) intByteCount += 8 dblXY = oPoint.Y bytData = BitConverter.GetBytes(dblXY) ReDim Preserve bytPoly(intByteCount + 8) Array.Copy(bytData, 0, bytPoly, intByteCount, 8) intByteCount += 8 Next Next Return bytPoly End Function 序列化后的数据可以作为一个原子值在程序或网络上传输,要想还原为原来的Polygon对象还需要以下反序列化程序: Public Function ConvertByteToPolygon(ByVal bytData() As Byte) As ESRI.MapObjects2.Core.Polygon Dim oPoly As New ESRI.MapObjects2.Core.Polygon Dim intByteCount As Integer = 0 Dim shtPartCount As Short shtPartCount = BitConverter.ToInt16(bytData, intByteCount) intByteCount += 2 Dim i As Short For i = 0 To shtPartCount - 1 Dim oPart As New ESRI.MapObjects2.Core.Points Dim shtPointCount As Short shtPointCount = BitConverter.ToInt16(bytData, intByteCount) intByteCount += 2 Dim j As Short For j = 0 To shtPointCount - 1 Dim oPoint As New ESRI.MapObjects2.Core.Point oPoint.X = BitConverter.ToDouble(bytData, intByteCount) intByteCount += 8 oPoint.Y = BitConverter.ToDouble(bytData, intByteCount) intByteCount += 8 oPart.Add(oPoint) Next oPoly.Parts.Add(oPart) Next Return oPoly End Function参考文献1 吴长悦,李国栋. MapObjects开发GIS软件技术简介J. 矿山测量. 2002,(2):16-172 翟长江,张秋文. 基于控件MapObjects开发GIS应用系统J. 微计算机信息. 2003,19(5):82-833 刘光,刘小东编著. 地理信息系统二次开发实例教程VB.NET和MapObjects实现M. 北京:清华大学出版社, 2004.54 王嘉彬. MapObjects 2.2在Visual Studio.NET环境
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 新能源电池隔板加工制造项目施工方案
- 土石方工程设备使用与管理方案
- 超高纯电子级气体生产建设项目建设工程方案
- xx市城乡供水安全保障一体化项目技术方案
- 冷冻法施工组织设计
- 中心城区地下管网改造项目节能评估报告
- 2025年新生入学考核题库及答案
- 老旧供水管网改造工程节能评估报告
- 跨区域口腔医院医生聘用及人才培养协议
- 离婚二次起诉书:共同债务清偿与财产分割协议
- 2025年度2025年少先队知识测试题及答案
- 九一八警钟长鸣强国有我+课件-2025-2026学年高一上学期爱国主义主题班会教育+-
- 勇气与成长写物作文10篇范文
- 反洗钱可疑交易识别课件
- 人教部编版小学三年级语文上册课后习题参考答案
- 光伏运维安全培训总结课件
- 2025年第九届全国中小学“学宪法、讲宪法”活动知识竞赛题库及答案
- 土石方运输居间合同范本土石方运输居间合同格式-仅供参考8篇
- 2025-2026学年人教版(PEP)三年级上册英语教学计划(三篇)
- 室外消火栓埋地施工方案
- 真人秀节目策划与执行方案
评论
0/150
提交评论