zhjm
路人甲
路人甲
  • 注册日期2003-12-05
  • 发帖数312
  • QQ
  • 铜币54枚
  • 威望0点
  • 贡献值0点
  • 银元0个
阅读:3294回复:9

MapObjects 2.2在.Net环境里的开发[转帖]

楼主#
更多 发布于:2003-12-11 18:27
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.NET]

 Dim pnt As ESRI.MapObjects2.Core.Point = New ESRI.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,实现如下:

Public Sub AddShpFile(ByVal FilePath As String, ByVal FileName As String)

  Dim dc As New DataConnection()

  dc.Database() = FilePath

  If dc.Connect Then

    Dim lyr As New MapLayer()

    lyr.GeoDataset = dc.FindGeoDataset(FileName)

    AxMap1.Layers.Add(lyr)

 Else

  MsgBox("No such a file exists")

End If

End Sub

然后在窗体上添加一个Button控件,并在它的Click事件里调用AddShpFile方法:

Private Sub Button1_Click(ByVal sender As System.Object, _

 ByVal e As System.EventArgs) Handles Button1.Click

 Dim FilePath As String = "D:\ESRI\MapObjects2.2\Samples\Data\World"

 Dim FileName As String = "country.shp"

'以上两行根据实际情况进行适当修改

AddShpFile(FilePath, FileName)

End Sub

此时按F5键运行程序,点击窗口上的Button1按钮,一幅世界地图就加载上来了。

 

2. 地图的放大、漫游和全景显示

在AxMap控件的MouseDownEvent事件里加入实现地图的放大和漫游的代码,如下:

Private Sub AxMap1_MouseDownEvent(ByVal sender As Object, _

ByVal e As ESRI.MapObjects2.Core.MouseDownEventArgs) Handles AxMap1.MouseDownEvent

If e.button = 1 Then

'在AxMap控件上按下鼠标左键后做拉框操作,实现地图放大功能

Dim pRect As Rectangle

pRect = Me.AxMap1.TrackRectangle

If Not pRect Is Nothing Then

Me.AxMap1.MousePointer = MousePointerConstants.moZoomIn

Me.AxMap1.Extent = pRect

End If

Else

'在AxMap控件上按下鼠标右键键后做拖动操作,实现地图漫游功能

Me.AxMap1.MousePointer = MousePointerConstants.moPanning

Me.AxMap1.Pan()

Me.AxMap1.MousePointer = MousePointerConstants.moPan

End If

End Sub

在AxMap控件的DblClick事件里加入实现地图全景显示的代码,如下:

Private Sub AxMap1_DblClick(ByVal sender As Object, _

ByVal e As System.EventArgs) Handles AxMap1.DblClick

'在AxMap控件上双击,实现地图全景显示功能

AxMap1.Extent = AxMap1.FullExtent

End Sub

 

3. 地图要素定位

在窗体上添加一个TextBox控件,在它的KeyDown事件里加入实现地图要素定位的代码,如下:

Private Sub TextBox1_KeyDown(ByVal sender As Object, _

ByVal e As System.Windows.Forms.KeyEventArgs) Handles TextBox1.KeyDown

If e.KeyCode = Keys.Return Then

Dim exp As String = "NAME = '" + TextBox1.Text + "'"

Dim lyr As MapLayer = Me.AxMap1.Layers.Item(0)

Dim recs As Recordset = lyr.SearchExpression(exp)

If Not recs.EOF Then

Dim res As Polygon = recs.Fields.Item("Shape").Value

Dim ext As Rectangle = res.Extent

ext.ScaleRectangle(2.0)

Me.AxMap1.Extent = ext

Me.AxMap1.CtlRefresh()

Me.AxMap1.FlashShape(res, 3)

End If

End If

End 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);

[Visual Basic]

Dim 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.NET]

Dim 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.NET]

Dim 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;

[Visual Basic]

Dim sym As ESRI.MapObjects2.Core.Symbol = New ESRI.MapObjects2.Core.SymbolClass()

sym.SymbolType = ESRI.MapObjects2.Core.SymbolTypeConstants.moFillSymbol
喜欢0 评分0
wangkb
路人甲
路人甲
  • 注册日期2005-03-09
  • 发帖数9
  • QQ
  • 铜币105枚
  • 威望0点
  • 贡献值0点
  • 银元0个
1楼#
发布于:2005-07-26 14:53
<P>正用的上</P>
举报 回复(0) 喜欢(0)     评分
鸟语花香
路人甲
路人甲
  • 注册日期2004-08-04
  • 发帖数102
  • QQ
  • 铜币51枚
  • 威望0点
  • 贡献值0点
  • 银元0个
2楼#
发布于:2005-07-28 21:39
you are a good man<img src="images/post/smile/dvbbs/em05.gif" />
举报 回复(0) 喜欢(0)     评分
afei0912
路人甲
路人甲
  • 注册日期2004-11-19
  • 发帖数5
  • QQ
  • 铜币116枚
  • 威望0点
  • 贡献值0点
  • 银元0个
3楼#
发布于:2005-09-08 21:00
<P>thanks</P>
举报 回复(0) 喜欢(0)     评分
yangsg
路人甲
路人甲
  • 注册日期2004-09-23
  • 发帖数83
  • QQ
  • 铜币41枚
  • 威望0点
  • 贡献值0点
  • 银元0个
4楼#
发布于:2005-09-09 10:04
不错,顶
举报 回复(0) 喜欢(0)     评分
ballstar
路人甲
路人甲
  • 注册日期2005-10-12
  • 发帖数10
  • QQ
  • 铜币120枚
  • 威望0点
  • 贡献值0点
  • 银元0个
5楼#
发布于:2005-10-12 17:50
好东西,多谢,已收藏
举报 回复(0) 喜欢(0)     评分
cafecat
路人甲
路人甲
  • 注册日期2003-07-29
  • 发帖数375
  • QQ
  • 铜币894枚
  • 威望0点
  • 贡献值0点
  • 银元0个
6楼#
发布于:2006-01-20 14:22
谢谢,有帮助
http://3s2go.blogspot.com/
举报 回复(0) 喜欢(0)     评分
zsuwqs
路人甲
路人甲
  • 注册日期2004-11-28
  • 发帖数34
  • QQ
  • 铜币248枚
  • 威望0点
  • 贡献值0点
  • 银元0个
7楼#
发布于:2006-02-09 00:37
<img src="images/post/smile/dvbbs/em01.gif" /><img src="images/post/smile/dvbbs/em02.gif" />
举报 回复(0) 喜欢(0)     评分
hn23559
路人甲
路人甲
  • 注册日期2003-09-18
  • 发帖数14
  • QQ
  • 铜币167枚
  • 威望0点
  • 贡献值0点
  • 银元0个
8楼#
发布于:2006-03-18 22:33
正想找这方面的资料,并且想尝试着用.net去开发一个WebGIS,不知道还有没有这方面更详细的资料,多谢了!!!
举报 回复(0) 喜欢(0)     评分
buterrm
路人甲
路人甲
  • 注册日期2006-05-12
  • 发帖数19
  • QQ
  • 铜币143枚
  • 威望0点
  • 贡献值0点
  • 银元0个
9楼#
发布于:2006-12-11 15:25
<P>不会</P>
<P>在学</P>
举报 回复(0) 喜欢(0)     评分
游客

返回顶部