---- 地理信息系统软件MapInfo在各行各业都有广泛的应用。由于本行业的需要,我们往往要对MapInfo进行二次开发。很多情况下是采用将MapInfo作为OLE对象集成到二次开发的应用程序中。开发的客户应用程序作为客户端运行在前台,直接与用户进行交互操作;MapInfo作为服务器在后台运行,对客户程序的请求做出回答。一般情况下,MapInfo不会自动地把信息传递给客户程序,是较为被动的角色。
---- 在一些情况,如将MapInfo状态栏的信息,如鼠标在地图上移动时鼠标所在位置的经纬度值、地图的编辑状态等等,需要及时地反映到客户应用程序的状态栏上,就需要MapInfo能够主动地发送信息。也即这时MapInfo要充当客户的角色,而原定的客户应用程序转为服务器的角色。MapInfo提供了这种自动发送信息给客户应用程序的功能——称为Callback(回调)。
---- 在下列情况下,Callback允许MapInfo 发送信息到您的客户应用程序:
---- 1. 用户使用定制工具与MapInfo窗口进行交互
---- 例如,用户在MapInfo的地图窗口上点击或者拖动鼠标进行画线时,MapInfo能够发送各点的经纬度信息给应用程序。
---- 2. 用户选择菜单命令
---- 例如,如果应用程序定制了MapInfo的快捷菜单,即右击菜单,当用户从快捷菜单中选择了定制的命令后,MapInfo就会通知应用程序去处理这个菜单事件。
---- 3. 地图窗口发生变化
---- 当用户改变窗口内容,如添加或删除图层时,MapInfo就会将发生变化的窗口的Windows ID号告知应用程序。这类似于MapBasic的WinChangedHandler。
---- 4. MapInfo中状态栏的内容发生变化
---- 对开发有用的状态栏的信息主要有图层信息,如图层的编辑状态、鼠标在地图上移动时鼠标所在位置的经纬度值等等。
---- 二、Callback的Delphi实现
---- 要实现Callback,您编制的客户应用程序必须能够充当DDE Server或OLE Server。现有的开发工具如VC++,Delphi,VB 等实现起来都很方便。我们这里将用Delphi来举例说明MapInfo Callback功能的实现——将MapInfo嵌入到客户程序中,客户程序的状态栏反映的是MapInfo状态栏的内容。
---- 用Delphi实现步骤如下:
- 新建一个工程,存为:CallbackExamv.pas。主窗体取名为:MainForm,程序单元存为Main.pas。
- 在MaiForm窗口中添加一状态栏,其缺省名字为StatusBar1。在StatusBar1上右击,从弹出菜单上启动Panels Editor,添加两个Panel。设置StatusBar1.Panel[0]的宽度为150,显示非MapInfo状态信息。
- 新建Automation Object单元。操作为:File|New —> ActiveX|Automation Object,启动Automation Object向导。Class Name设为:MiCallBack。确认后,Delphi打开“Type Library”编辑器。
Type Library”编辑器是个很不错的可视化工具,它会自动生成和维护类型库文件(包括两个部分:一个是已编译好的类型库,扩展名为CallbackExam_TLB.TLB;另一个为相应的接口源文件,扩展名为CallbackExam_TLB.PAS)和自动化对象的实现文件(保存为callback.pas)。“Type Library”编辑器缺省生成对象MiCallBack和对象调度接口IMiCallBack的GUID。我们主要的工作是编辑接口IMiCallBack,设计生成所需的成员函数或数据。 - 创建IMiCallBack的成员函数SetStatusText。操作为:在“Type Library”编辑器里选中IMiCallBack,点击编辑器的工具栏“New Method”按钮,改新建的函数名为SetStatusText,到“Parameters”页添加参数satusText,类型设为WideString。在“Text”页可看到如下:
procedure SetStatusText(satusText: WideString) [dispid $00000001]; safecall; - 在callback.pas中编写成员函数SetStatusText的实现程序。
在interface中加入对Main.pas单元的引用:
interface
uses
ComObj, ActiveX, CallbackExam_TLB, main;
成员函数SetStatusText的改动如下:
procedure TMICallBack.SetStatusText(const statusText: WideString);
begin
MainForm.Statusbar1.Panels[1].Text := statusText;
// statusText传递MapInfo的状态信息,并在状态栏的第二列中显示
End; - 在main.pas中实现MapInfo的OLE集成和Callback。
定义全局变量oleMapInfo。
在单元的implementation部分加入对callback.pas和CallbackExam_TLB.pas的引用
增加窗体MainForm的OnCreate事件,并在该事件内实现MapInfo的OLE集成和Callback。程序如下:
var MainForm : TMainForm; oleMapInfo : variant; implementation uses Callback, CallbackExam_TLB; {$R *.DFM} procedure TMainForm.FormCreate(Sender: TObject); //OnCreate事件 var msgString : String; sWinHand : String; theResponder : TMICallBack; begin try //MapInfo OLE服务器的ProgID 为MapInfo.Application oleMapInfo := CreateOLEObject('MapInfo.Application'); except ShowMessage('请先安装MapInfo软件!'); Application.Terminate ; {如不存在MapInfo或安装的MapInfo没有在系统注册, 程序退出。在Dos命令行下,进入MapInfo目录, 运行MapInfow –regServer 可使MapInfo在系统中注册} end; //Callback对象的生成 theResponder := TMICallBack.create; // Callback对象作为接口被MapInfo OLE对象设置挂钩 oleMapInfo.SetCallback(theResponder as IMICallBack); {下面语句重新定向MapInfo的文档窗口到panel1上, 使MapInfo的地图窗口能在应用程序中显示。} Str(panel1.Handle, sWinHand); msgString := 'Set Next Document Parent ' + sWinHand + ' Style 1'; oleMapInfo.Do(msgString); msgString := 'Set Application Window ' + sWinHand; oleMapInfo.Do(msgString); //打开地图并显示, msgString := 'Run Application "' + ExtractFilePath(Application.EXEName) + 'test.wor"'; oleMapInfo.Do(msgString); end;---- 7. 编译执行。在地图上移动或点击鼠标,将会有相应的提示信息显示。