『公告』 预祝您龙年大吉,万事如意, 过节期间, 大家如需数据服务,请拨打400 或直接添加客服微信,再祝大家龙年,心想事成。
关注我们 新浪 腾讯
首页 -> 3S基础知识 -> MapInfo-> 正文

MapInfo教程--二次开发入门

MapInfo教程--二次开发入门
       MapBasicMapinfo自带的二次开发语言,它是一种类似Basic的解释性语言,利用MapBasic编程生成的*.mbx文件能在Mapinfo软件平台上运行。
       一、利用MapBasic开发

       MapBasicMapinfo自带的二次开发语言,它是一种类似Basic的解释性语言,利用MapBasic编程生成的*.mbx文件能在Mapinfo软件平台上运行,早期的Mapinfo二次开发都是基于MapBasic进行的。MapBasic学起来容易,用起来却束缚多多,无法实现较复杂的自定义功能,用它来建立用户界面也很麻烦,从现在角度看,MapBasic比较适合用于扩展Mapinfo功能。       

       二、利用OLE自动化开发

       1. 建立Mapinfo自动化对象

       基于OLE自动化的开发就是编程人员通过标准化编程工具如VCVBDelphiPB等建立自动化控制器,然后通过传送类似MapBasic语言的宏命令对Mapinfo进行操作。实际上是将Mapinfo用作进程外服务器,它在后台输出OLE自动化对象,供控制器调用它的属性和方法。

       OLE自动化开发的首要一步就是建立Mapinfo自动化对象,以Delphi为例(后面都是如此),你可设定一个Variant类型的全程变量代表OLE自动化对象,假设该变量名为olemapinfo,那么有:

       oleMapinfo := CreateOleObject('Mapinfo.Application')  

       一旦OLE自动化对象建立,也就是后台Mapinfo成功启动,你就可以使用该对象的Do方法向Mapinfo发送命令,如:

       oleMapinfo.Do('Set Next Document Parent' + WinHand + 'Style 1') 

       这一命令使Mapinfo窗口成为应用程序的子窗口,WinHand是地图窗口句柄,style 1 是没有边框的窗口类型。你还可以使用自动化对象的Eval方法返回MapBasic表达式的值,如下面语句返回当前所打开的表数:

       TablesNum:=olemapinfo.eval('NumTables()')

       你也可以直接调用Mapinfo菜单或按钮命令对地图窗口进行操作,如地图放大显示:

       oleMapinfo.RunMenuCommand(1705) 

       2. 建立客户自动化对象触发CallBack

       基于OLE自动化开发的难点在于所谓的CallBackMapinfo服务器对客户程序地图窗口的反应叫CallBack,假如你在地图窗口中移动地图目标,Mapinfo能返回信息告诉你地图目标当前的坐标位置,这就是CallBack功能。如果你想定制自己的地图操作工具或菜单命令,你必须依靠CallBack。但是想捕获CallBack信息,你的客户程序必须具备接收CallBack信息的能力,为此需要在客户程序中定义自己的OLE自动化对象,如:

       //定义界面

  IMyCallback = interface(IDispatch)

       ['{2F4E1FA1-6BC7-11D4-9632-913682D1E638}']

       function WindowContentsChanged(var WindowID: Integer):SCODE;safecall;

       function SetStatusText(var StatusText: WideString): SCODE; safecall;

  //定义界面实现 

       TMyCallback = class(TAutoObject, IMyCallback)

       function SetStatusText(var StatusText: WideString): SCODE; safecall;

       function WindowContentsChanged(var WindowID: Integer): SCODE;safecall;

       其中WindowContentsChanged函数用于返回变化窗口的ID号,即当地图窗口变化时(如放大、缩小),让Mapinfo将地图窗口的ID号返回给客户程序; 另一个SetStatusText函数返回Mapinfo状态条变化信息。编程人员不能随意定义这些函数,因为只有在三种情况下Mapinfo服务器的CallBack才会被触发:(1)地图窗口发生变化,触发函数为WindowContentsChanged(2)Mapinfo状态条信息改变,触发函数为SetStatusText(3)用户选择自定义工具或菜单命令在地图窗口上操作,如用户定制的画线工具,当用户在地图窗口画线时触发MapinfoCallBack返回线的坐标位置。

       建立客户自动化对象后,调用MapInfo自动化对象的SetCallback方法将客户自己定义的自动化对象告诉Mapinfo,只要程序一运行,客户自动化对象就会自动在注册表中注册,然后就能收到CallBack信息了,如:

   My:=MyCallBack.Create

 oleMapInfo.SetCallBack(My) 

       这里打一个比方我想会有助于理解上述机制,客户程序与Mapinfo之间的交互就像舞台指挥与木偶演员的交流,客户程序中的地图窗口或说Mapinfo子窗口只不过是一个牵线木偶,后台的Mapinfo才是真正操纵木偶的演员,所以客户程序必须与后台Mapinfo建立正向、反向的联系机制,才能操纵地图窗口中的图形目标。

       三、利用MapX开发

       1. 掌握使用MapX

       MapXMapinfo公司最新推出的ActiveX控件产品,目前已经发展到MapX4.5。由于MapX是基于Windows操作系统的标准控件,因而能支持VCVBDelphiPB等标准化编程工具,使用时只需将控件装入开发环境,装入控件后,开发环境ActiveX工具条上会增加一个控件按钮Map,把它拖放到窗体上就可建立一个TMap类型的ActiveX地图对象Map,通过设置或访问该Map对象的属性、调用该Map对象的方法及事件,便能快捷地将地图操作功能溶入到你的应用程序中。

       MapX由一系列Object(对象)Collection(对象集合)组成,Map是最基本的对象,每个MapLayer()Dataset(数据集)Annotation(标注)这三个对象及对象集合(LayersDatasetsAnnotations)来定义, 其中Layer用于操作地图图层,Dataset用于访问空间对象的属性数据,Annotation用于在地图上添加文本、符号等标注,掌握上述三个主要对象的特征后,再顺藤摸瓜掌握下一级对象的特征,如每个Layer又由Feature(点、线、面、文本图形目标)对象及对象集合(Features)定义,每个DatasetField(属性数据域)对象及对象集合(Fields)定义......,这样很快就能把MapX学到手。

       2. 定义地图坐标系

       在MapX开发中需要特别注意地图坐标系问题,MapX地图坐标系分为地图显示坐标系和内部计算坐标系,两者互为独立,在GIS应用开发中根据应用需要设置好这两种坐标系非常重要,因为坐标系一方面影响软件系统的内部坐标处理,另一方面影响地图的外观显示。Map对象的坐标系及投影通过CoordSys对象的Set方法定义:

  Set(Type, [Datum], [Units], [OriginLongitude], [OriginLatitude], 

   [StandardParallelOne], [StandardParallelTwo], [Azimuth], [ScaleFactor], 

   [FalseEasting], [FalseNorthing], [Range], [Bounds], [AffineTransform])

       其中主要参数:Type表示投影类型,Type1时地图坐标以经纬度表示,后面都为可选参数,其中Datum为地球基准面;Units为坐标单位,如Units7表示以米为单位;OriginLongitudeOriginLatitude分别为起始经度和纬度;StandardParallelOneStandardParallelTwo为第一、第二标准纬线,该参数与地图投影相关。

       通过设置Map对象的DisplayCoordSysNumericCoordSys属性返回的CoordSys对象,就可设定地图显示坐标系和内部计算坐标系。举例如下:

   procedure TMain.DefineMapParam();

   var

    MapDatum: Variant;//地球基准面

   begin 

   try

MapDatum := CreateOleObject('MapX.Datum.4'); //建立基准面对象

//定义北京54坐标系基准面

// (Ellipsoid, ShiftX, ShiftY, ShiftZ, RotateX, RotateY, RotateZ, ScaleAdjust, PrimeMeridian)

MapDatum.set(3, 24, -123, -94, -0.02, 0.25, 0.13, 1.1, 0);

//定义北京54坐标系经纬度作为内部计算坐标系 

Map1.NumericCoordSys.Set_(1, MapDatum);

//定义北京54坐标系30度标准纬线麦卡托投影作为显示坐标系,单位为米

Map1.DisplayCoordSys.Set_(26,MapDatum,7,0,0,30);

finally

VarClear(MapDatum);

end;

坐标系是GIS系统的基石,正确设置坐标系是系统成败的关键。

       3. 操纵地图对象

       你可以简单地加载一个GeoSet文件,给Layers对象集合赋予具体的内容,随之在Map对象中就能看到地图显示,GeoSet文件类似MapInfo中的工作空间,MapX中带有Geoset文件的编辑器GeosetMangater.exe,用户可在编辑器中组合及设置图层,然后保存生成一个 *.gst 文件直接调入Map对象,这样可以节省时间。你也可以通过Layers对象的Add Remove 方法添加或移走地图图层,如:

Map.layers.Add(FileName); // 添加图层,FileName为文件全路径名

Map.Layers.Remove(3); // 移走地图第三层

Layers对象由一组Layer对象组成,通过Layer对象的FeaturesSelection对象集合你可以操纵和选择图层上的图形目标,如:

Map.Layers.Item(1).AddFeature(Newobj); //将新建对象Newobj添加到图层一

       4. 地图数据捆绑

       数据捆绑是将不同来源的数据对应到地图层的过程,捆绑结果会产生一个Dataset对象,Dataset对象的集合组成Datasets Collection,它定义了Map对象的数据集属性。 你可以通过Datasets将不同来源的数据捆绑到地图上实现图文互动,或创建专题图,如下例ODBC Access数据的捆绑及专题分析:

   procedure TMapForm.ODBC1Click(Sender: TObject);

   var

  param: ODBCQueryInfo ; 

ds: Dataset; //定义数据集

Datafields: Fields; //定义数据域

begin

param.SqlQuery := 'select * from China'; //选择Access数据库中的China 

param.DataSource := 'MapChina'; //ODBC 数据源名

param.ConnectString := 'ODBC;'; //或是user = ... Pwd = ... , 定义ODBC连接

Datafields.Add('GEONAME','GEONAME', miAggregationAuto,miTypeString); //添加数据域GEONAME

Datafields.Add('POPU','POPU', miAggregationAuto,miTypeNumeric); //添加数据域POPU

//Access数据捆绑到Mapinfo China

ds := Map.Datasets.Add(miDataSetODBC, param, unassigned, unassigned, unassigned, 'CHINA', Datafields, unassigned); 

ds.Themes.Add(miThemeRanged, 'POPU', 'MyTheme'); //添加一个范围专题图 

end;

       5. 建立客户定制工具

你还可以定制自己的地图操作工具,下面通过定制一个名为Info的信息按钮工具简述方法步骤:

(1)定义客户工具常量 

    Const CUSTOM_INFO_TOOL = 1

(2)利用Map对象的CreateCustomTool方法定义客户工具,方法为:

   CreateCustomTool (ToolNumber, Type, Cursor, [ShiftCursor] , [CtrlCursor], [InfoTips])

其中ToolNumber为工具号,即上面定义的常量;Type为工具类型;Cursor为光标形状,其他参数可选。 

//定义Info工具为十字光标点触发工具

 Map.CreateCustomTool(CUSTOM_INFO_TOOL, miToolTypePoint, miCrossCursor, miArrowCursor, miArrowCursor, unassigned)

(3)Map对象事件ToolUsed中编写工具的Handler(操作内容) 

 procedure TMain.MapToolUsed(Sender: TObject; ToolNum: Smallint; X1, Y1, X2, Y2, Distance: Double;

                Shift, Ctrl: WordBool; var EnableDefault: WordBool);

 begin

 Case ToolNumber of

CUSTOM_INFO_TOOL : //信息工具Info

try 

……

end;

(4)定义信息按钮的Click事件

procedure TMain.InfoClick(Sender: TObject);

begin

Map.CurrentTool:=CUSTOM_INFO_TOOL;

end 

       四、小结

       基于MapBasic的开发简单但受限制较多,比较适合Mapinfo功能扩展编程。而基于OLE自动化的开发比较繁琐,因为需要来回向后台的Mapinfo发送MapBasic字符串命令,所建立的应用程序运行速度也相对较慢,但这种开发方法能随心所欲制作出美观友好的界面,将地理操作与非地理操作溶为一体,并且能实现几乎100%Mapinfo功能,这是目前的MapX4.5也不能比拟的。与传统GIS专业性开发环境相比,像MapX这类组件式GIS系统的出现可说是一种质的飞跃,它小巧灵活,开发简捷,价格便宜,以后会越来越大众化。 MapX开发的GIS系统运行速度快,因为它不需要在Mapinfo软件平台上运行。但从目前MapX4.5看,MapX并没能实现所有的Mapinfo功能(据称95%以上),使用过程中发现其生成或编辑地图能力及地理分析能力不足,而且里面Bug也不少,当然随着今后新版的推出,MapX会越来越稳定、完美。

      京ICP备08100627号-22 京公网安备 11010802030428号