应用Visual Basic的事件机制设计可复用的大粒度GIS组件

 

1.       引言

当前地理信息系统的应用需要GIS与与MIS、OA等其它系统的有机集成,因此,大多数的GIS系统开发都选择以组件式GIS为核心进行二次开发。因此,随着计算机和地理信息技术的飞速发展,以及GIS理论与应用的逐渐成熟,组件式技术已逐渐成为GIS 软件的主流,改变了传统集成式GIS 平台的工作模式。代表性的组件式GIS有ERSI的ArcGIS和北京超图的SuperMap Object。
在组件式GIS的开发中,由于GIS功能和用户界面要求按照需求进行定制,而GIS的大多数功能的调用都需要调用底层的GIS组件进行实现,因此,每次的开发都需要对一些重复的GIS基本功能或核心功能进行编码和实现,工作异常的繁琐且易出错。例如,地图的浏览功能(包括大小缩放、漫游、显示控制等)在几乎所有的GIS系统中都要求实现,而其核心实现又都是基于GIS组件的,因此,在开发过程中,开发人员常常需要一遍遍的实现类似功能。
本文将介绍基于VB的事件机制和对象委托方式将类似功能封装成一个COM组件的思路和方法。

2.       Visual Basic的事件机制

Visual Basic是并不是一个优秀的面向对象语言,但在Visual Basic中也可以完全开发具有属性、方法、事件(P-M-E)COM组件。下面将详细介绍VB6的事件处理过程。
在VB中,事件的定义和触发的语法如下:
在Class(类)中定义:
       ○ 事件定义:Event  …
       ○ 事件触发:RaiseEvent  …
而客户代码事件处理使用如下语法:
       ○ 第一,定义事件处理对象:Dim WithEvents ObjectXX As Class
       ○ 第二,处理事件:
 
       Private Sub ObjectXX_EventName
       …
       End Sub
 
对于一般情况下,窗体、控件的使用,其实并不需要这么使用,因为有缺省的事件处理过程,例如Form_Load事件,Command1_Click事件等等,我们只需要相应其事件就可以了。但是,如果在一个Form内有一个Command1的按钮控件,那么,我们可以定义以下的事件处理程序:
 
Private Sub Command1_Click()
       MsgBox "Old Test"
End Sub
 
另外,我们还可以定义另外一个处理过程:
 
Dim WithEvents SS As CommandButton
 
Private Sub SS_Click()
       MsgBox "New Test"
End Sub
 
执行则可以看到,两个过程都可以响应执行。因此,通过WithEvents定义的事件处理过程可以在单独的模块或类里,这样就可以隔离程序的界面和具体逻辑,这也就是本文需要应用的技术。
其实对于VB.net或者C#,事件处理的方法和VB6在形式上并没有很大的差别,差别只是VB6中有缺省的事件处理过程;如同VB6有缺省的窗体一样,你可以这样使用:Form1.show,而在VB.net中必须先创建一个form,然后才可以调用。

3.       应用实例

应用以上方法和技术,我们将基于北京超图公司的SuperMap Object组件式GIS先创建一个可以重复使用的地图浏览的控件,并且通过一个简单的项目来测试其正确性。

3.1.    可重复使用的地图浏览控件MapView

首先,启动VB6,创建一个ActiveX 控件项目,给该项目添加一个工具条控件,添加必要的按钮。
其次,我们需要添加对SuperMap Object组件的引用,在该组件的代码中添加如下声明:
 
Dim SW As SuperWorkspace
Dim SM As SuperMap
 
Private WithEvents EventSM As SuperMap
 
第一、二句声明了工作空间和地图对象,第三句声明了地图对象事件的处理对象。给该控件添加一个连接方法,使声明的工作空间和地图空间指向项目中的实际控件:
 
Public Function Connect(objSW As Object, objSM As Object) As Boolean
    If objSW Is Nothing Or objSM Is Nothing Then
        Connect = False
    Else
        Set SW = objSW
        Set SM = objSM
        Set EventSM = SM
        Connect = True
    End If
End Function
 
其中,传入的参数将工作空间和地图声明为Object类型是因为这两个控件都是不可创建的,因此不能在参数中声明。其他代码很简单,只是将传入的控件实例赋给控件中的工作空间和地图对象。其中Set EventSM = SM初始化EventSM对象,使EventSM对象可以处理地图对象的事件。然后,对于地图操作,我们就可以使用这两个对象(SW和SM)来进行了。例如地图缩放:
 
……
Case "ZoomIn"
     SM.Action = scaZoomIn
Case "ZoomOut"
     SM.Action = scaZoomOut
……
 
对于工作空间和地图对象的事件处理,因为在控件开始声明了具体的事件处理对象“EventSM”,利用此对象,即可对相应的事件进行处理。以下两个过程,第一个当地图重画后更新地图比例尺的显示,第二个在选中地图对象后,调用一个过程显示相应对象的属性。
 
Private Sub EventSM_AfterMapDraw(ByVal hdc As stdole.OLE_HANDLE)
    '地图比例尺
    If SM.ViewScale <> 0 Then
        Combo1.Text = "1:" & Format(1 / SM.ViewScale, "#")
    End If
End Sub
 
Private Sub EventSM_GeometrySelected(ByVal nSelectedGeometryCount As Long)
    '调用属性显示过程显示选中对象属性
    ShowObjectInfo SM
End Sub
 
这样,我们就可以把地图浏览显示的一些代码封装在一个控件内,而无需关心其实现,只要在代码中将其和实际的地图和工作空间对象连接即可使用。

3.2.    MapView地图浏览控件的使用

新建一个VB6工程,添加相应的SuperMap Object控件和MapView控件,调整其到合适的位置,在FormLoad事件里添加如下代码:
 
If Me.SuperWorkspace1.Open("…") Then
    Me.SuperMap1.Connect Me.SuperWorkspace1.Handle
    Me.SuperMap1.OpenMap "World"
    If Not Me.MapView1.Connect(Me.SuperWorkspace1, Me.SuperMap1) Then
           Unload Me
    End If
End If
 
程序与控件的连接语句只需“MapView1.Connect”,运行程序,可以看到地图浏览控件实现的地图浏览已正确的运行,见下图:

     

4.       结论

基于以上方法,笔者应用VB6实现了基于SuperMap Object的地图浏览控件,该控件只需要在初始化时调用Connect语句,与SuperMap Object的工作空间控件和地图控件连接,即可实现地图的缩放、平移、图层控制、属性的SQL查询、将当前地图输出为图片和打印当前地图等功能。该控件及其示例代码可在笔者的Blog下载。
应用Visual Basic的事件处理机制,以及合适的面向对象的设计,一方面,我们可以将在项目开发中经常需要使用的组件GIS的功能封装成独立的组件,可以大大的加快开发速度,避免不必要的错误,减少应用逻辑、程序界面、GIS实现之间的耦合,提高开发质量;另一方面,通过此类方法,可以在实际开发中进行合理的分工合作,提高工作效率。
 
本文代码开发和测试环境:
  • Windows XP Sp1
  • Visual Basic 6 (Sp6)
  • SuperMap Object 3

https://files.cnblogs.com/maweifeng/MapView.rar

posted on 2004-12-21 12:09  马维峰  阅读(2481)  评论(0编辑  收藏  举报