MapInfo概论
?第一讲 MapInfo简介及基本概念
?第二讲 MapInfo基本操作 —表
?第三讲 MapInfo查询及分析
?第四讲 空间分析及属性信息图形化
?第五讲 OLE 嵌入与 MapBasic 简介
?第六讲 MapInfo集成地图开发
?第七讲 组件式 GIS与 MapX基础
?第八讲 MapX二次开发
上节总结:
1,MapBasic的软件集成环境,
( 1) 文本编辑器,用于程序的编辑与修改;
( 2) 程序编译器,用于源程序编译,生成可执行程序;
( 3) 程序链接器,将若干独立的模块链接成一个应用程序;
( 4) 联机帮助,提供 MapBasic 每条语句或函数的详细说明资料
mb文件 → mbx文件; mb文件 → mbo文件+ mbp文件 → mbx文件
2、创建、编译和链接项目文件( Project File ),
[link]- Application- Module
mbp文件+ mbo文件- mbx可执行文件 (实例)
3、程序组织,Include,mapbasic.def”
Type … End Type
Declare/Declare function
Define /Global
Sub Main … End Sub
Sub … End Sub
Function … End Function
4、事件处理程序:
单击鼠标或其他由用户发出的动作称为事件。
事件处理程序,WinClosedHandler,WinChangedHandler、
ToolHandler, EndHandler 等
程序运行时,MapBasic自动调用相应程序,不需要在主过程中调用
,只在程序开头声明即可。
5,对于 定长字符串 变量,MapBasic总是用 空格 去填充不足部分 ;
6,如果在字符串常量里本身就有 双引号,那么需要插入 两个连续
的双引号到这个字符串中,例如:
Note,The Table,“World”” is already open.”
这个语句的运行结果是显示下面的一条信息:
The Table,World” is already open.
7,值参数传递 ( ByVal)
( 1) 在 Call语句中不必一定要为参数指定一个变量名 。 可以指定一个
变量名, 常量值或其他的表达式 。
( 2) 如果在子过程中赋了一个新的值给值参数, 将不影响调用者 。 换
句说话, 子过程不能通过值参数把一个值返回给调用者 。
8、访问表的指定列:
tablename.columnname; tablename.coln; tablename.col(n)
9、创建一个新表,Create table tablename
用 Create Index给一个表增加索引
Create Index on Cust(CustID)
用 Create Map使一张表可地图化
Create Map For Cust Coordsys Earthy
10、修改表结构,Alter Table
修改之前应该先保存该表,Commit Table
或放弃当前编辑,Rollback Table
11、顺序文件的输入 /输出:
Open File filename For Input/Output/Append As #1
用 Input#或 Line input#语句读文件,用 Write#语句写数据到文件中。
12、随机文件的输入 /输出:
Open File,filename” For Random As #1 Len=length
用 Get和 Put语句读写数据
13、二进制文件的输入 /输出:
Open File,filename” For Binary As #1
可以用 Get和 Put语句读写数据
14、如何查询、创建、修改地图对象,Obj
?第六讲 MapInfo集成地图开发
一、创建用户界面
1.1 菜单( menu)
1.2 工具条 ( ButtonPads)
1.3 对话框 ( Dialog)
1.4 窗口( Windows)
二,MapInfo集成地图开发
2.1 集成地图开发的概念
2.2 MapInfo集成地图开发过程
2.3 回调( Callbacks)
2.4 程序运行语句
一、创建用户界面
1.1 菜单( menu)
菜单栏- Menu Bar ;菜单- Menu ; 菜单项- Menu Item
① 新建菜单,Create Menu,MenuName” as“SubMenuName” calling Sub
② 新建菜单栏,Create Menu Bar As
恢复 MapInfo标准菜单栏,Create Menu Bar As Default
③ 增加 /移除菜单项,Alter Menu add / remove
加分割线, (-”
④ 增加 /移除菜单,Alter Menu Bar Add / remove,Menuname”
建立好的菜单需要把它加到菜单栏上才能看得见,
Alter Menu,Menuname” Add,Menuname1” As,Menuname1”
⑤ 修改菜单项,Alter Menu Item 过程 Enable/Disable/Check/Uncheck
灰化一个菜单项,在菜单项名字的第一个字母前加,(”
快捷键的定义,用键盘来使用菜单,在想定义的快捷键的字母前加字符 &
热键的定义,执行菜单命令的组合键
·PushButton——触发式按钮 。 如图层控制按钮,
特点,用户单击一个触发式按钮时, 按钮仍会弹回来 。
·ToggleButton——开关式按钮 。 如图例窗口显示 /隐藏按钮,
特点,用户单击按钮时, 按钮变成两种状态中的一种, 即
按下或弹起 。
·ToolButton——工具按钮, 如选择按钮,
特点,用户单击按钮时, 一个工具将处于激活状态, 直到
用户选择了另一个按钮 。
新建工具条:
Create ButtonPad,名称, as PushButton/ToggleButton/ToolButton
一、创建用户界面
1.2 工具条( ButtonPads)
修改工具条的属性,AlterButtonPad“主 /绘图, Add/Remove
可以重定位, 显示 /隐藏工具条或增加删除工具条中的工具 。
修改单个工具的状态,Alter Button
查询用户使用按钮的信息,Commandinfo()
工具条信息,ButtonPadInfo()
恢复标准工具条,Create ButtonPads As Default
一、创建用户界面
1.3 对话框( Dialog)
1、标准对话框:
( 1)询问对话框,Ask ( prompt,ok_text,cancel_text )
Dim more As Logical
more = Ask("Do you want to continue?","OK","Stop")
( 2)显示信息对话框,Note message
Note "Total # of records processed," + Str$( i_count )
( 3)状态条,ProgressBar
ProgressBar "Writing data..." Calling write_out Range 600000
( 4) FileOpenDlg( path,filename,filetype,prompt )
Dim s_filename As String
s_filename = FileOpenDlg("","","TAB","Open Table")
( 5) FileSaveAsDlg ( path,filename,filetype,prompt )
2、创建用户自定义对话框:
Dialog
[ Title title ]
[ Width w ] [ Height h ] [ Position x,y ]
[ Calling handler ]
Control control_clause
[ Control control_clause,,, ]
MapBasic对话框控件类型,Control 子句控制
3、修改对话框:
Alter MapInfoDialog dialog_ID
Alter MapInfoDialog dialog_ID Default
一、创建用户界面
1.4 窗口( Windows)
Map,Browse,Graph,Layout; Create Redistricter
1、显示 /隐藏窗口,Open/Close Window
MapBasic,Statistics,Legend,Info,Ruler,Help,Message
2、新建窗口,Map From
统计窗口,Graph Country,Population From Selection
Layout Position (0,0) Width 2 Height 4
创建重新分区窗口:
Create Redistricter source_table By district_column
创建图例窗口,Create Legend
[ From Window window_ID ]
[ { Show | Hide } ]
3、窗口 ID号:
获取活动窗口所 ID号,FrontWindow()
例,Dim map_win_id As Integer
Open Table "states"
Map From states
map_win_id = FrontWindow()
4、设置各种不同的窗口,
Set browse ; Set Legend; Set Map; Set Window;
Set Paper Units; Set LayOut,Set Redistrict
5、保存窗口:
Save Window ; Save WorkSapce
例,Save Window i_mapper_ID As "riskmap.wmf" Type "WMF "
6、计算窗口数目:
NumWindows(),NumAllWindows()
二,MapInfo集成地图开发
2.1 集成地图的概念
1、集成地图开发的概念:
将 MapInfo地图窗口集成在用其它语言编写的应用程序中
的开发方式,叫做 集成地图开发 。
利用其它平台能够调用 MapInfo环境下的数据、图形等,
应用程序可以控制集成地图的外观、部分执行过程,甚至生成
完全不同于 MapInfo界面的应用程序。
注意:
MapInfo在后台运行。
可以用 Visul Basic,VC++,Delphi等可视化的开发环境,
集成 MapInfo窗口到非 MapBasic应用程序中,特别是原有成熟
的应用系统中,增加 GIS的功能。
集成地图开发是在程序中调用语句( MapBasic语句)来在
后台启动 MapInfo应用程序,MapInfo在后台运行,并不显示
启动窗口。集成地图窗口与 MapInfo中的地图窗口没有本质的
区别。
在集成地图应用程序中,首先构造代表 MapBasic语句的字
符串,然后使用 OLE技术或者 DDE技术(动态数据交换)将字
符串发送给 MapInfo,从而可以操纵 MapInfo,MapInfo会像
处理 MapBasic语句一样处理这些命令字符串。
例如,打开地图窗口,在 MapBasic编程中采用 Map From 语
句即可。但是,在集成地图应用程序中,必须给出附加的语句
(如 Set Next document Parent ),使地图窗口首先成为当前
应用程序的子窗口。该过程通常称为,重父化( reparenting)
窗口”。然后才可以使用 Map From 语句打开地图窗口。
二,MapInfo集成地图开发
2.2 MapInfo集成地图开发过程
客户应用程序
VB,VC++ MapInfo应用程序OLE,DDE
发送 MapBasic语句
MapInfo返回信息 —回调
MapBasic程序
可选
OLE 自动化,不是 OLE嵌入
重父化,hWnd
一个简单的示例程序:
集成地图的 VB编程开发步骤如下:
1、启动 MapInfo
调用 VB的 CreateObject()函数,并对返回的 VB对象变量进
行赋值,可将该对象定义为全局变量。如:
Dim miApp as object
Set miApp =CreateObject(“mapinfo.application”)
miApp.do,set application window, & Form1.hWnd
要调用已运行的 MapInfo,则使用 GetObject()函数连结
Set mapinfo= GetObjec (,,mapinfo.application”)
CreateObject ()和 GetObject()函数均使用 OLE自动对象连结
MapInfo,DDE技术在此不做介绍。
2、向 MapInfo传送命令
启动 MapInfo后,就可构造代表 MapBasic语句的字符串。
如希望 MapInfo执行 MapBasic的打开表,需构造如下字符串:
msg=“open table”“world.tab”“Interactive”
然后使用 Do方法,向 MapInfo发送字符串命令,例如
miApp.do msg ( miApp 为定义的启动 MapInfo的全局变量 )
可以在一条命令行中合并多个 MapBasic语句,利用 &连结。
msg=,open table”“usa”“Interactive”
msg=msg &,Set Next Document Parent, & Form1.hwnd &,Style1”
msg=msg &,Map from usa”
Miapp.do msg
注意:关键词后面的空格是必要的! 重父化
因为存在空格,当 MapInfo解析命令行时,能自动检测出 msg
包含 3个独立的 MapBasic语句,Open table,Set Next Document,
Map From,MapInfo通过保留关键字 Open,Set,Map来辨别。
3、从 MapInfo中查询数据
如果需要查询 MapBasic表达式的值,需构造代表该表达式
的字符串。例如,如果希望判断 MapBasic的 WindowID(0)函数
的返回值,在 VB中可以按照如下方式构造:
① msg=“WindowID(0)”
② 采用 OLE自动化:
Dim result as String
result=miApp.Eval,WindowID(0)”
解释,MapInfo将该字符串解释为 MapBasic表达式,确定
该表达式的值,然后以字符串的形式返回给 VB应用程序。
注意,MapBasic语句中关键词后的 空格, 双引号里面的语
句最后有一个空格,如,set application window,,否则与 VB
语句连接时将出错!
4、定位 MapInfo窗口
(1) 重定位 MapInfo父窗口
启动 MapInfo后,采用 MapBasic语句的 Set Application
Window语句可以使客户程序拥有 MapInfo的对话框和错误信
息对话框。
Msg=“Set Application Window, & Form1.hWnd
miApp.do msg
(2) 重定位文件窗口
需要在 VB应用程序中集成 MapInfo窗口时,需要向 MapInfo
发送 MapBasic创建窗体的 Set Next Document 语句,以及创建
该窗口的 MapBasic语句。如:
Msg="Set Next Document Parent " & Form1.hWnd & "
Style 1/Style2/Style3 "
Mymap.do msg
Mymap.do "Map from world"
mapid=Val(miApp.eval(“WindowID(0)”))
重父化窗口为窗口重新指定一个父窗口,指定应用程
序中一控件的句柄,下次当创建 MapInfo窗口,使用 Map、
Browse,LayOut或 Create Legend语句时,新建的窗口被
重父化好了,这些地图窗口就将已指定的应用程序作为
它们的父窗口。
即使地图窗口重新指定了父窗口,MapInfo仍然能够
维护该窗口,如果部分窗口需要刷新,MapInfo自动刷新
该窗口,因此客户应用程序可以不考虑擦除和刷新重父
化的窗口。
Set Next Document 多个地图窗口
(3) 重定位图例和特殊窗口
① 特殊窗口
MapInfo包括信息 (Info)、标尺 (Ruler)、消息 (Message)和统
计 (Statics)窗口等特殊的浮动窗口,重父化这些窗口,需要
MapBasic的 Set Window语句。如:
miApp.do,Set window Info Parent,& form1.hWnd
重父化信息窗口与重父化地图窗口不同原因:
MapInfo可有多个地图窗口,但 只有一个 信息窗口。
② 图例窗口
,Set Next Document, &地图窗口,hWnd。
再用 Create Legend语句 不同于 MapInfo的默认图例窗口
自定义的图例窗口不会自动刷新
图例窗口与地图窗口或统计图窗口绑在一起。
miApp.do,Set Window Info Parent, & Form1.hWnd
5、允许用户定义地图窗口大小
MapInfo不会依据新窗口的大小自动重新设置地图以填满窗
口,因此要实现改变地图窗口大小的功能,必须利用 Windows
API函数 MoveWindow编写代码来实现
Declare Function MoveWindow Lib "user32" (ByVal hwnd As Long,_
ByVal x As Long,ByVal y As Long,_
ByVal nWidth As Long,ByVal nHeight As Long,_
ByVal bRepaint As Long) As Long
Private Sub Form_Resize()
dim mHwnd as long
mHwnd=Val(miApp.Eval(“WindowInfo(FrontWindow(),WIN_INFO_WND)”))
MoveWindow(mHwnd,0,0,ScaleWidth,ScaleHeight,0)
End Sub
FrontWindow():返回当前活动窗口的整型 ID号,
WindowInfo(要返回的信息的窗口的整型 ID号 )
Scalemode属性设置为 Pixels(象素)
由示例程序演示( API函数浏览器)
6、集成 MapInfo工具按钮
在 VB应用程序中可集成 MapInfo中所有工具按钮的功能,如
放大、缩小等,但是由于不能对 MapInfo的工具栏进行重父化,
因此如果在应用程序中需要工具按钮,只能在应用程序开发环
境中自己创建。如果希望所创建的 VB工具栏按钮能仿效标准的
MapInfo按钮,可以使用 MapInfo的 RunMenuCommand方法。
可设置信息提示如下:
miApp.RunMenuCommand 1707/M_TOOLS_PNT_QUERY
既可以使用数字,也可使用 标识符,若使用标识符,必须在
程序中包含 MapBasic头文件,如果开发环境是:
VB——MapBasic.bas;
VC++(C++ Builder)——MapBasic.h;
MapBasic——MapBasic.def
Main工具条:
选择,M_TOOLS_SELECTOR = 1701
矩形选择,M_TOOLS_SEARCH_RECT = 1722
圆选择,M_TOOLS_SEARCH_RADIUS = 1703
多边形选择, M_TOOLS_SEARCH_BOUNDARY = 1704
放大,M_TOOLS_EXPAND = 1705
缩小,M_TOOLS_SHRINK = 1706
平移,M_TOOLS_RECENTER = 1702
信息查询,M_TOOLS_PNT_QUERY = 1707
标注,M_TOOLS_LABELER = 1708
拖放窗口,M_TOOLS_DRAGWINDOW = 1734
标尺,M_TOOLS_RULER = 1710
Draw工具条:
点符号,M_TOOLS_POINT = 1711
直线, M_TOOLS_LINE = 1712
折线,M_TOOLS_POLYLINE = 1713
弧,M_TOOLS_ARC = 1716
多边形,M_TOOLS_POLYGON = 1714
椭圆,M_TOOLS_ELLIPSE = 1715
矩形,M_TOOLS_RECTANGLE = 1717
圆角矩形,M_TOOLS_ROUNDEDRECT = 1718
文本,M_TOOLS_TEXT = 1709
框架,M_TOOLS_FRAME = 1719
增加节点,M_TOOLS_ADD_NODE = 1723
7、子定义 MapInfo快捷菜单
可以使用 MapBasic语句增加 /删除快捷菜单中的一个或多个
命令。
Alter Menu…Add Calling OLE 增加
Alter Menu…Remove 删除
可使用 Create Menu语句重新定义菜单,并使用,(-”代码作
为新菜单定义。
如删除 MapInfo地图窗口中的快捷菜单:
miApp.do "Create Menu ""MapperShortcut"" ID 17 as ""(- "" "
8、打印 MapInfo集成窗口
应用 MapBasic的,PrintWin”语句可以打印 MapInfo窗口。
MiApp.do,PrintWin”
也可先利用 MapBasic的,Save Window”语句输出一个窗口
图元文件 (WMF)来替代地图的打印,然后应用 VB的
,PrintForm”
9,错误捕获
VB,On Error GoTo
VC++,try ….catch….finally
10、终止 MapInfo的运行
通过 CreateObject()创建 MapInfo应用程序对象,如果
释放该对象变量,则终止 MapInfo的运行。所以 miApp应
该作为全局变量,如果是局部变量的话,子程序结束时,
miApp就会释放,MapInfo终止运行。
Set miApp =Nothing
二,MapInfo集成地图开发
2.3 回调( Callbacks)
1、回调概述
前面介绍了如何向 MapInfo发送命令,我们还希望
MapInfo能把信息发送到应用程序中。如当地图窗口改变时,
希望 MapInfo能通知应用程序,并告知改变的窗口 ID,程序
员可在应用程序中编写相应的响应代码。
这种获得 MapInfo发送回来的消息的通讯机制称作 回调 。
下面几种情况下,允许 MapInfo向客户应用程序发送信息,
( 1) 用户使用自定义工具与 MapInfo窗口进行交互。 如用
户在地图窗口中单击并拖动鼠标绘制一条直线,MapInfo可
以告诉客户程序用户选择的 x,y坐标;
( 2) 用户选择了菜单命令。 假如应用程序自定义了
MapInfo的快捷菜单,当用户从快捷菜单中选择了命令时,
MapInfo可以通知客户程序来调用该菜单事件;
( 3) 当地图窗口发生改变时。 如果用户选择了地图窗口中
的内容,(如增加或删除了图层,或漫游地图 ),MapInfo可以
告诉客户程序该 窗口的 ID号,与 MapBasic的特殊处理进程
winChangedHandler类似;
( 4) 当 MapInfo状态栏中的文本发生改变时。 MapInfo的状
态栏不会显示在集成地图窗口中,如果希望模拟 MapInfo的
效果,必须编写 代码 。无论状态栏文本发生何种变化,
MapInfo都能通知应用程序。
利用 OLE自动服务器功能完成回调。
2、如何使用 OLE回调
( 1)采用 VB4.0以上版本或其它能支持 OLE服务器的语言,创
建一个能定义一个或多个 OLE方法 的 类 ;
( 2)如果模拟 MapInfo的状态栏,创建 SetStatusText方法,对
该方法进行定义使其能获取一个 字符串变量 ;
( 3)如果希望在每次地图窗口改变时 MapInfo能通知客户程序,
创建 WindowContentsChanged方法,定义该方法能获取一个 4
字节 整数大小的 变量,代表该 MapInfo窗口的 ID号;
( 4)如果使用自定义菜单命令或按钮,希望 MapInfo能通知客
户程序,可以创建一个或多个 额外的方法,所定义的每一个方
法能获取一个 字符串变量 ;
( 5) 用自定义的类来创建对象,
Public myCallback As New CMyClass
( 6)在程序启动 MapInfo后,调用 MapInfo的 SetCallback方法,
然后指定该对象名:
mapinfo.SetCallback myCallback
( 7)如果希望当用户在使用自定义工具栏按钮时,MapInfo向
客户程序发出通知,可以自定义按钮,如:
Alter ButtonPad…Add Calling OLE
( 8)如果希望当用户使用菜单命令时,MapInfo向客户程序发
出通知,可以使用诸如, Alter Menu…Add Calling OLE”的
语句来 自定义菜单命令;
( 9) 在所定义的方法内,编制必要的处理程序来处理 MapInfo
传送来的变量 。
3、处理回调数据
在集成地图应用程序中,创建自定义的 MapInfo菜单命令和
工具按钮后,使用回调机制来处理 MapInfo发送给应用程序的
数据。当用户选择这些命令和按钮后,MapInfo向 OLE方法发
送一个 由逗号分隔的包含 8个元素的字符串 。
例如:
MI,-73.5548,42.122,F,F,-72.867702,43.025,202,
如果熟悉 MapBasic的 CommandInfo()函数, 那么很容易明
白该逗号分隔的字符串的内容 。 编写 MBX应用程序时是通过
调用 MapBasic处理程序的子过程句柄, 来实现自定义菜单命令
和自定义按钮的 。
在子过程句柄中, 通过调用 CommandInfo()函数来判断当前
事件的不同信息 。 如判定在 MapBasic编程中使用自定义绘制工
具按钮时是否按下 shift键 。
Log_variable=CommandInfo(CMD_INFO_SHIFT)
CommandInfo()函数的意义:
1 CMD_INFO_X 第 1点的 X坐标
2 CMD_INFO_Y 第 1点的 Y坐标
3 CMD_INFO_SHIF 按下 Shift
4 CMD_INFO_CTRL 按下 Ctrl
5 CMD_INFO_X 第 2点的 X坐标
6 CMD_INFO_Y 第 2点的 Y坐标
7 CMD_INFO_TOOLBTN 用户点击的 ButtonID
8 CMD_INFO_MENUITEM 用户点击的 MenuID
当创建自定义的菜单或按钮,并使用, Calling OLE方法名,
语句指定该菜单命令或按钮相应的方法后,MapInfo就会使
用上述 8个返回值构造一个由逗号分割的字符串 。该字符串始
终以, MI:”为前缀,通过该前缀,OLE服务器可以判断是
MapInfo调用了该方法。
MapInfo发送给方法的字符串结构如下:
,MI:”+”CommandInfo(1)”+,CommandInfo(2)”
+,CommandInfo(3)” +,CommandInfo(4)”
+,CommandInfo(5)” +,CommandInfo(6)”
+,CommandInfo(7)” +,CommandInfo(8)”
如果在集成地图应用程序中,MapInfo的快捷 菜单 中增加了
一个自定义菜单 (ID:101),则 MapInfo发送的字符串为,
MI:,,,,,,,101
如果用户创建了一个自定义 按钮,实现用户在地图窗口中
单击并拖动鼠标绘制一条直线,则 MapInfo发送的字符串为:
Mi:-10.26,42.12,F,F,-80.13,100.2,2002,
x1 y1 x2 y2 ButtonID,空值
如果为每个自定义的按钮指定了唯一的 ID,可以让按钮调
用同一个方法,然后在方法中通过检验字符串的第 7个元素,来
判断用户选择的是哪个按钮。
一旦 MapInfo将由逗号分割的字符串发送给应用程序的方法,
方法中必须增加代码来解析字符串,执行代码。
二,MapInfo集成地图开发
2.4 程序运行语句
1、运行 MapBasic应用程序 (MBX)或添加 MapInfo工作空间
Run Application file(可执行文件)
终止,Terminate Application
例如:
MiApp.do,Run Application,“C:\mapbasic\app\report.mbx”””
MiApp.do,Run Application,“parcels.wor”””
2、运行其他程序
Run Program Program_spec 命令字符串
例如,Run Program,notepad.exe readme.txt”
注意尽量避免多任务处理可能引起的冲突,可将 Run Program
语句放置在处理事件语句之后。
欢迎多提宝贵意见!
谢谢!