你好,欢迎来到电脑编程技巧与维护杂志社! 杂志社简介广告服务读者反馈编程社区  
合订本订阅
 
 
您的位置:杂志经典 / 图形图象处理与游戏编程
5.18 应用COM技术扩展ArcGIS的功能(上)
 

一、COM技术

COM即组件对象模型,是英文“Component Object Model”的简称,它不是一种编程语言,而是一种规则,一种能使各软件组件进行相互作用的二进制标准。COM是微软制定和倡导的,现在Windows平台用COM服务程序开发的软件几乎无处不在。

1.工作原理

COM的工作过程涉及客户端、服务器端、COM API及注册表,其关系如图1所示。

  



图1 COM工作过程

客户端通过调用COM API ,并通过指定相应的参数,发出服务请求;COM API是微软开发的一套接口,提供了一套整齐、标准以及在一定程序上透明的方法来与服务器交换数据。通过COM API这个基本框架,比较容易开发客户/服务器程序。COM API检查客户端给出的参数,并从系统注册表中获得指定服务器的文件名,因为COM服务器在安装到机器上时需要注册,并在注册表中留下相应的记录;系统装载服务器的DLL(或EXE),并创建请求的对象,然后返回对象的指针;客户端通过指针操纵该对象,获得相应的服务。

2.应用特征

1)应用程序级的重用

软件最大限度的重用一直是软件开发者追求的目标之一,采用COM规范开发的对象具有良好的可重用性,能够方便地在任何支持COM技术的开发语言环境中使用。COM开发技术的发展,使得开发人员能够用自已最熟悉的语言开发组件对象。一部分人开发组件对象,一部分开发人员调用这些对象共同完成一个项目的开发,实现代码真正意义上的重用。同时也为程序的二次开发打下了基础,如我们熟悉的Microsoft OfficeAutoCAD等软件提供的Automation开发接口为二次开发专门应用创造了条件。同时,随着面向对象技术的发展,在源代码重用的基础上,应用程序级的重用很好地保护了厂商的知识产权和提高了重用的层次。

2)组件的的构建

COM是一类系统应用程序接口,它允许应用程序访问其他应用程序(EXE)或动态链接库(DLL)中的数据和函数。当把应用程序放到一个COM里,其他遵守该标准的人也能访问它。

开发COM意味着开发用户接口,所有COM组件之间通信都是通过组件接口执行的。所有的COM对象都必须实现一个IUnknown接口。COM中包括两种成员,即属性和方法,属性是数据成员,方法是函数成员。

COM接口是抽象的,它不与任何工具直接相连。COM是连接一个组件或模块同其他组件或模块的协议。使用COM可以重新利用分布系统中动态变换的软件组件。COM不指定应用程序如何被创建,用户可以选择支持COM的任何开发环境。COM允许在二进制的基础上重新利用组件。第三方开发人员在扩展系统时不需要访问源代码、标题文件和对象库。在再也看不到源代码的时候,接口成了唯一的选择,二进制重用代替了源代码重用。另外,当一个接口被发布后就不能改变其外部特征,但可以更改一个对象执行时的输出接口。

3)本质特征

COM是一个与操作平台无关的、分布的、面向对象的机制,它能创建可以交互的二进制软件模块。COM的本质特征是COM对象的接口与实现的分离。在COM技术中,接口(Interfaces)是只定义了一组相关函数的原型的“协议”。一个接口定义通常指明了自身的成员函数、返回类型、参数数量、类型和功能。至于成员函数的功能是如何实现的、接口本身并不关心。接口定义好后不得改变,而功能的实现可以灵活编写与修改。这种机制既保证了组件之间交互的一致,也方便了以后的升级。

4)客户/服务器

COM技术中有客户端和服务器端之分,服务器端提供功能,客户端使用功能。COM是两种组件之间的通信设施,一个单独的组件既可以做为客户端也可以做为服务端。有三种类型的COM类:Abstract Class(抽象类)、CoClass(组件对象类)和ClassCOM接口是每个COM对象之间的通讯方法,当使用COM对象开发软件时,开发人员不能直接使用COM对象,而是通过接口访问对象得到服务。COM接口被设计为一组逻辑相关函数,这些虚函数可以在客户端调用,在服务器端实现。

5)支持多语言的共同开发

可以使用多种编程工具编写COM服务器,如我们熟知的Visual BasicVisual C++Visual J++Delphi等。在开发一个大型的系统时,可以把整个工程划分为数个DLL构件,分给不同的程序员,每个程序员可以使用自已最得心应手的开发工具来开发,最后将各个组件组装在一起,形成完整的系统。而且每个通用的组件还可用于其他系统中,从而避免许多重复开发。COM是微软公司提出来的,理想的编制语言是微软公司的Visual C++ Visual Basic,最适合COM应用的平台是Windows系列。

早期开发COM组件比较复杂,程序员不得不一次又一次地与IUnknowIDisptch等接口打交道。现在可视化技术的发展,使得开发COM组件越来越容易,面向对象的技术隐藏了具体的实现细节,能够自动生成COM接口所需的代码。特别是当你用Visual Basic来开发COM服务器时,接口的定义对程序员来说是透明的,程序员可以专注于具体的业务逻辑。

二、ArcGIS简介

ArcGIS是美国ESRI公司开发的一个全系列地理信息系统(GIS)平台,整合了GIS与数据库、软件工程、人工智能、网络技术及其他多方面的计算机主流技术。ArcGIS是一个统一的地理信息平台,由三个重要组成部分组成:ArcGIS桌面软件,一个一体化的高级的GIS应用;ArcSDE通路,一个用于数据管理系统的(RDBMS)管理空间数据的接口;ArcIMS软件,基于Internet的分布式数据和服务的GIS。应用ArcGIS,可完成从简单到复杂的GIS工作。由于ArcGIS的模块化和可伸缩性,在构造系统时提供了很大的灵活性。它既可以是一个独立的应用,也可以是跨越全球的分布式网络应用。通过面向对象的组件技术构建,可以和大量的程序分享核心应用、用户界面和概念。

ESRIArcObjectsArcMapArcCatalogArcSceneArcGIS系列应用程序中的开发平台。ArcObjects组件展现了ArcGIS中可以利用的全部的功能。为定制应用程序提供了基本的框架。ArcGIS是用基于面向对象的组件技术开发而成,是一个非常庞大的系统,而ArcObjects是构建ArcGIS的核心和基石,实际上它是一个巨大的组件集,ArcGIS81800个组件,据说最新的9.2版包含3000多个组件、10000多个接口,而微软的MFC也仅有数百个组件。这样一个庞大的系统采用传统的软件开发来构建,是不可想象的。

ArcGIS是一个通用的地理信息平台,能为我们做许多工作,但针对具体的应用,从软件的合理配置、易用性、及工作效率来考虑,常常不得不做一些改变。ArcGIS通常可以在三个层次上进行客户化:

1)菜单功能重组,通过拖放实现,简单易行,无须编程。

2VBA编程,通过内置的VBA脚本编辑器实现,可满足大多数应用的编程需要。

3)应用COM编程,满足高级开发需求。

ArcGISArcObjects组件集提供了大量组件和接口。接口分两种:入接口(inbound interface)和出接口(Outbound interface)。COM调用可以是单向的,即客户程序创建组件对象,然后客户程序调用对象所提供的功能,在适当时候再把对象释放掉,通常称为入接口。如果一个COM对象支持一个或多个主动与客户程序进行通信的接口,则这种接口称为出接口,是因为这些接口并不由对象实现,而是由客户程序实现。

ESRI应用程序是COM的客户端,它支持不同软件组成,可以指定不同语言编写的组件。这些组件能容易地添加到应用程序中。在VB中可以很容易地建立在ArcMapArcCatalog中使用的ActiveX DLL进程内服务器程序。

ArcGIS很好地体现了COM对象的接口与实现的分离的特征,服务的接口在ESRI的组件集中被定义,而服务的具体实现则可以推迟到用户创建的COM服务器DLL中。在用户的COM服务器中通过实现特定的接口,完成接口定义的所有方法和属性,该组件能被ArcGIS的应用作为一个进程内服务器调用,从而完成客户端。实际上我们编写的COM服务器,相对于调用它的应用而言是服务器,而相对它调用的底层ArcObjects组件而言,它又是客户端,所以这个COM组件的本身兼具服务器和客户端的双重角色。

下面以一个具体的实例介绍如何使用COM技术,实现客户化来扩展ArcGIS的功能。

客户化的目的和内容:Windows图形界面程序呈现在用户面前的是一个窗口,窗口包含菜单、工具条、工具按钮、客户区等。ArcMapArcGIS桌面系统中的一个应用程序,同样具有上述窗口特征。通过创建ActiveX DLL服务器组件,实现系统特定的接口,从而创建自已的菜单和工具条,包括命令按钮和交互工具等,方便使用。

三、具体实现

1.创建ActiveX DLL进程内服务器组件

打开VB6.0,新建工程,选择工程类型为ActiveX DLL;选择菜单[工程/引用],打开引用对话框,显示系统注册的类型库,选择引用必要的ESRI类型库;添加几个类模块,在类模块中实现普通按钮、交互工具、泊钨窗、工具条、菜单接口。VB6中有一个“Implements”语句帮助我们来实现一个接口。接口就是代表接口封装的成员(方法以及属性)的原型集合;也就是说,它只包含成员过程的声明部分。一个类提供一个或多个接口的所有方法以及属性的一种实现方案。类的控制者每次调用函数时,该函数所执行的代码由类来提供。接口中的所有成员都要在这个类模块中实现,否则会出现编译错误。

普通按钮实现ICommand接口的核心代码如下:

'类模块:cmdOpenCoverage.cls

Implements ICommand

Dim m_Bmp As IPictureDisp

Private Sub Class_Initialize()

  Set m_Bmp = LoadResPicture(102, 0) '从资源文件中读取一个位图资源

End Sub

Private Sub Class_Terminate()

    Set m_Bmp = Nothing

End Sub

Private Property Get ICommand_Bitmap() As esriSystem.OLE_HANDLE

    ICommand_Bitmap = m_Bmp

End Property

Private Property Get ICommand_Caption() As String

    ICommand_Caption = "打开Coverage"

End Property

Private Property Get ICommand_Category() As String

    ICommand_Category = "刘新定创建"

End Property

Private Property Get ICommand_Checked() As Boolean

End Property

Private Property Get ICommand_Enabled() As Boolean

    ICommand_Enabled = True

End Property

Private Property Get ICommand_HelpContextID() As Long

End Property

Private Property Get ICommand_HelpFile() As String

End Property

Private Property Get ICommand_Message() As String

    ICommand_Message = "打开Coverage  刘新定2007.6.20"

End Property

Private Property Get ICommand_Name() As String

    ICommand_Name = "打开Coverage"

End Property

Private Sub ICommand_OnClick()

    frmOpenCoverage.Show

    If IsIconic(frmOpenCoverage.hwnd) <> 0 Then

        ShowWindow frmOpenCoverage.hwnd, SW_RESTORE

    End If

End Sub

Private Sub ICommand_OnCreate(ByVal hook As Object)

    Set m_pArcMapApp = hook '获得Arcmapapplication实例指针,将其保存到全局变量中

End Sub

Private Property Get ICommand_Tooltip() As String

    ICommand_Tooltip = "打开Coverage  刘新定2007.6.20"

End Property

交互工具实现ICommand ITool两个接口的核心代码如下:

'类模块:toolQueryAttribe.cls

Option Explicit

Implements ICommand

Implements ITool

Dim m_Bmp As IPictureDisp '按钮的位图

Dim m_Cursor As IPictureDisp '光标

Private Sub Class_Initialize()

    Set m_Bmp = LoadResPicture(101, 0) '0表示BITMAP

    Set m_Cursor = LoadResPicture(201, 2) '2表示CURSOR

End Sub

Private Sub Class_Terminate()

    Set m_Bmp = Nothing

    Set m_Cursor = Nothing

End Sub

Private Property Get ICommand_Bitmap() As esriSystem.OLE_HANDLE

    ICommand_Bitmap = m_Bmp

End Property

Private Property Get ICommand_Caption() As String

    ICommand_Caption = "属性查询"

End Property

Private Property Get ICommand_Category() As String

    ICommand_Category = "刘新定创建"

End Property

Private Property Get ICommand_Checked() As Boolean

End Property

Private Property Get ICommand_Enabled() As Boolean

    ICommand_Enabled = True

End Property

Private Property Get ICommand_HelpContextID() As Long

End Property

Private Property Get ICommand_HelpFile() As String

End Property

Private Property Get ICommand_Message() As String

    ICommand_Message = "属性查询  刘新定2007.7.3"

End Property

Private Property Get ICommand_Name() As String

    ICommand_Name = "属性查询"

End Property

Private Sub ICommand_OnClick()

End Sub

Private Sub ICommand_OnCreate(ByVal hook As Object)

    Set m_pArcMapApp = hook '获得Arcmapapplication实例指针,将其保存到全局变量中

End Sub

Private Property Get ICommand_Tooltip() As String

    ICommand_Tooltip = "属性查询  刘新定2007.7.3"

End Property

Private Property Get ITool_Cursor() As esriSystem.OLE_HANDLE

    ITool_Cursor = m_Cursor

End Property

Private Function ITool_Deactivate() As Boolean

    ITool_Deactivate = True

    frmQueryAttribe.Hide '隐藏属性信息窗口

End Function

Private Function ITool_OnContextMenu(ByVal X As Long, ByVal Y As Long) As Boolean

End Function

Private Sub ITool_OnDblClick()

End Sub

Private Sub ITool_OnKeyDown(ByVal keyCode As Long, ByVal shift As Long)

End Sub

Private Sub ITool_OnKeyUp(ByVal keyCode As Long, ByVal shift As Long)

End Sub

Private Sub ITool_OnMouseDown(ByVal button As Long, ByVal shift As Long, ByVal X As Long, ByVal Y As Long)

  Dim pMxApp As IMxApplication

  Dim pDoc As IMxDocument

  Dim pMap As IMap

  Dim pIdentify As IIdentify

  Dim pIDArray As IArray

  Dim pFeatIdObj As IFeatureIdentifyObj

  Dim pIdObj As IIdentifyObj

  Dim pRowObj As IRowIdentifyObject

  Dim pFeature As IFeature

  Dim tol As Long

  Dim pEnv As IEnvelope

  Dim r As tagRECT

  Set pDoc = m_pArcMapApp.Document

  Set pMap = pDoc.FocusMap

  If TypeOf pDoc.ContentsView(0).SelectedItem Is IIdentify Then

        Set pIdentify = pDoc.ContentsView(0).SelectedItem

  Else

        MsgBox "请先在图层管理窗口中选择要查询的图层!" & vbCrLf & "组图层或单个要素层均可。", vbOKOnly + vbInformation, "温馨提示"

        Exit Sub

  End If

  frmQueryAttribe.Show  '打开信息显示窗体

  Set pMxApp = m_pArcMapApp

  Dim pApp As IApplication

  Set pApp = m_pArcMapApp

  tol = pDoc.SearchTolerancePixels

  r.Left = X - tol

  r.Top = Y - tol

  r.Right = X + tol

  r.Bottom = Y + tol

  Set pEnv = New Envelope

  pMxApp.Display.DisplayTransformation.TransformRect pEnv, r, esriTransformPosition + esriTransformToMap

  Set pEnv.SpatialReference = pMap.SpatialReference

  Set pIDArray = pIdentify.Identify(pEnv)

    Dim szName As String 'Field

    Dim szValue As String 'value

    Dim str As String

    Dim i As Integer

  If Not pIDArray Is Nothing Then

    If pIDArray.Count = 0 Then

        Exit Sub

    End If

    Set pRowObj = pIDArray.Element(0)

    Set pFeature = pRowObj.Row

   Set pIdObj = pRowObj

    pIdObj.Flash pMxApp.Display

    Dim pField As IField

    Dim fT As esriFieldType

    For i = 0 To pFeature.Fields.FieldCount - 1

        Set pField = pFeature.Fields.Field(i)

        szName = pField.Name

        fT = pField.Type '字段类型

        If szName <> "Shape" Then '图形数据除外

            Select Case fT  '判断数据类型

                Case esriFieldTypeDouble '双精度数

                    szValue = Format(pFeature.Value(i), "###.###")

                Case esriFieldTypeSingle '单精度数

                    szValue = Format(pFeature.Value(i), "###.###")

      

                Case Else

                    szValue = pFeature.Value(i)

            End Select

            str = str & szName & " = " & szValue & vbCrLf

        End If

    Next i

    frmQueryAttribe.lblInfo.Caption = str  '在窗口中显示信息

    Dim 代码值 As String

    代码值 = pFeature.Value(pFeature.Fields.FindField("code"))

 Else

  推荐精品文章

·2024年9月目录 
·2024年8月目录 
·2024年7月目录 
·2024年6月目录 
·2024年5月目录 
·2024年4月目录 
·2024年3月目录 
·2024年2月目录 
·2024年1月目录
·2023年12月目录
·2023年11月目录
·2023年10月目录
·2023年9月目录 
·2023年8月目录 

  联系方式
TEL:010-82561037
Fax: 010-82561614
QQ: 100164630
Mail:gaojian@comprg.com.cn

  友情链接
 
Copyright 2001-2010, www.comprg.com.cn, All Rights Reserved
京ICP备14022230号-1,电话/传真:010-82561037 82561614 ,Mail:gaojian@comprg.com.cn
地址:北京市海淀区远大路20号宝蓝大厦E座704,邮编:100089