Ⅰ 有一個VB和mapinfo的問題
如果你是在做MapInfo嵌入自動化編程的話,可以實現。
但是看你問的意思,大概只是簡單的OLE鏈接編程,這樣是實現不了你的目的。
要說的話非常復雜,沒法說清。最好看看書,或者直接去找源代碼回來改改,會很快。
推薦一本書,名字叫做《MapInfo地理信息系統二次開發實例》,電子工業出版社的。這本書帶光碟,裡面有源代碼,你考一個,稍微改一改就能實現你要的功能,照我說的做,代碼考我下面寫的2句就可以。
首先在你打開的工作空間(wor文件)里加入你已經做好的表,注意,只是打開,但是不添加到地圖窗口裡面。
在你的commandbutton裡面加入如下代碼:
Tablename= Text1.Text & "到" & Text2.Text
MapInfo.do "Add Map Layer """ & TableName & """" ------這個語句是自動加上圖層而且放在最上層。
或者你告訴我一個信箱,我把代碼發給你
已經做好了,我的信箱是[email protected]。你給我發信。
Ⅱ VB如何調用mapinfo
首先要購買mapinfo runtime版。其中提供了控制項,放在form上可以顯示圖形;另有很多組件(.dll),在VB中引用,然後調用其中的方法完成諸如繪圖、放大、縮小等功能。
Ⅲ vb調用VC回調函數的問題,會出現內存錯誤是什麼回事
Public Function SetCallBack_WhiteList(ByRef Rect As tagWhiteListCallBack) As Integer
在VB里定義的回調函數和VC里的回調函數完全不一致,作為函數指針參數傳給TPE_SetCallBack_WhiteList當然會有問題。
VC里的返回值是int,VB里應該定義成Function... As Integer,不是Sub。
我不知道tagWhiteListCallBack是個什麼類型的,在VC里的回調函數是個tagWhiteListCallBack的指針,但在VB里使用的卻是ByVal As Double?
基礎知識很弱,有理由懷疑程序里還有其他錯誤,10個錯誤,排除了9個,程序還是一堆不能運行的代碼。譬如,VB、VC切換時留心過__stdcall和__cdecl嗎?VC默認使用__cdecl的,VB是__stdcall。小地方的區別需要十分當心。
說話不中聽,沒有惡意,只是覺得樓主做東西操之過急。
=====================================================================
不是這個理。這句話也是需要推敲的。
已經說了,程序可能不止1,2個錯誤。改正了第一個錯誤後,程序因為第二個錯誤,依然無法順利運行,但不能因此說第一個錯誤沒改正對。於是,把第一個錯誤又恢復原樣,再修改第二個錯誤,改正後,程序因為第一個錯誤又無法運行了,是不是還要判斷第二個錯誤沒改正對?
其實,這是一種很簡單的邏輯思維,和計算機無關,樓主的理科學得可好?
Ⅳ 怎麼用delphi7.0操作mapinfo電子地圖(急)
摘要:本文以Delphi應用程序為例,比較詳細的介紹了如何利用OLE自動化技術集成開發MapInfo應用程序。介紹了OLE調用、回叫等功能的使用方法。最後,以一個例子說明了如何在實際應用程序中用到本文所講的方法。
關鍵詞:OLE自動化;MapInfo;地圖集成化
1 概述
MapInfo Professionnal 6.0是美國MapInfo公司開發的一種桌面地理信息系統開發平台,因為它小巧玲瓏、易學易用,同時對空間數據具有強大的採集、存貯、分析等功能,所以成為世界上最為流行的桌面地理信息系統。目前利用MapInfo開發應用程序主要有三種方式。分別是單純利用MapBasic開發、利用可視化編程工具集成二次開發和利用MapX開發。
在這三種方法中,單純MapBasic編程由於缺乏可視化編程環境的支持,開發周期過長而較少採用,後兩種是實際應用中比較常用的方法。
利用MapX開發的應用程序因為不需要後台MapInfo的支持,所以運行速度快,小巧靈活,是目前比較流行的開發方法,然而MapX並沒有實現所有的MapInfo功能,而且其生成和編輯地圖的能力尚有欠缺。相信隨著更高版本的MapX的推出,這種開發方法將會越來越流行。
利用可視化編程工具集成開發是在前台利用可視化編程工具(VC、VB、Delphi等)開發與地理信息功能無關的用戶界面,在涉及到地理信息功能時在後台調用MapInfo。實際上是將地圖窗口集成到其它編程語言開發的應用程序中,用其它編程語言通過向MapInfo傳送命令來控制MapInfo。這種方法能隨心所欲製造出美觀友好的界面並且能實現幾乎所有的MapInfo功能,尤其是需要在原有成熟的應用系統中增加地理信息管理功能時,這種方法是非常有效的。
2 OLE調用方法介紹
應用程序向MapInfo傳送命令主要通過有兩種途徑:
一種是利用DDE技術建立MapInfo和應用程序之間的通信。DDE會話是兩個Windows應用程序交換信息的過程。只有當兩個支持DDE的應用程序運行時,它們之間才可以進行DDE會話。在一個會話中,只有一個應用程序是主動的,成為客戶,被動的應用程序成為伺服器。實際運行時,MapInfo充當伺服器的角色,被客戶應用程序調用。
另一種向MapInfo傳送命令的方法是OLE自動化技術。MapInfo允許其他支持OLE功能的應用程序把MapInfo作為一個對象加以調用,MapInfo作為一個OLE伺服器向其他應用程序提供它的對象,而客戶應用程序則使用它的對象,其他應用程序通過調用OLE自動化對象的方法、屬性來操作MapInfo。
實際應用中,利用OLE是較為常用的方法,因為它比DDE穩定可靠,同時它還能報告MapInfo的運行錯誤,而DDE不能獲取MapInfo的錯誤代碼。本文主要討論基於OLE自動化的集成開發。
以Delphi集成MapInfo為例,利用OLE自動化集成開發方法如下:
a) 啟動MapInfo
在客戶程序中啟動MapInfo用如下語句來實現:
var oleMapInfo : Variant; //在Delphi應用程序中聲明OLE Variant類型的變數
oleMapInfo := CreateOLEObject('MapInfo.Application');
CreateOLEObject()函數用來創建MapInfo自動化伺服器的一個實例,上述語句同時把該函數的返回值賦給Variant類型的變數oleMapInfo,通過上述語句,oleMapInfo對象被定義為MapInfo的一個實例,在以後的操作中,oleMapInfo就相當於一個MapInfo伺服器,Delphi應用程序通過對oleMapInfo的調用,就相當於對MapInfo的進行管理和操作。
b) 調用MapInfo實例的方法和屬性
OleMapInfo對象擁有以下方法和屬性
對象
方法
屬性
Application
Do、Eval、RunCommand、SetCallBack 、RunMenuCommand、DataObject、
Name、Application、Parent、Version、Visible、LastErrorCode等
在應用程序中調用不同的方法和屬性可以實現不同的功能,其中經常用到的有:
1) Do方法—向MapInfo傳送指令
啟動MapInfo後就可以向它傳送MapBasic指令,讓其實現相應MapBasic語句對應的功能。例如下述語句打開並調入一幅地圖:
MsgString := 『Open Table 「D:\Map\Map1.Tab」 Interactive』;
oleMapInfo.Do(MsgString);
MsgString := 『Map From Map1』;
oleMapInfo.Do(MsgString);
Do方式是集成開發用到最多的一種方法,基本上一些重要的功能都要用它來實現。下面列舉一些。
①、重生成MapInfo窗口
當啟動MapInfo之後,通常要做的第一步是重生成MapInfo窗口:
MsgString := 'Set Next Document Parent ' + sWinHand + ' Style 1';
//sWinHand是Delphi容納MapInfo窗口的控制項的句柄
oleMapInfo.Do(MsgString);
當執行完上述語句後,MapInfo的對話框和錯誤信息就為客戶程序所擁有。
②、直接運行Mapbasic程序
有的時候,需要在二次開發中調用現成的MapBasic程序實現特定的功能,用Do方法實現如下:
MsgString := 'Run Application " D:\MapBasic\DrawArc.MBX"';
oleMapInfo.Do(MsgString);
③、重定義MapInfo右鍵菜單
這是一項很有實際意義的功能,開發者可以根據實際需要增加或者修改MapInfo地圖窗口的右鍵菜單,甚至完全屏蔽MapInfo的右鍵菜單:
MsgString := 'Create Menu "MapperShortcut" ID 17 As "(-"'; //屏蔽右鍵菜單
oleMapInfo.Do(MsgString);
2) Eval方法—從MapInfo獲得返回值
oleMapInfo的Eval方法可以從MapInfo中返回值給客戶程序。當客戶程序需要得到某些地圖信息時,需要應用此方法。下面的語句將地圖中心的橫、縱坐標返回給客戶程序:
MsgString := 'MapperInfo(WindowID(0), 3)';
CenterLongitude := oleMapInfo.Eval(MsgString);
MsgString := 'MapperInfo(WindowID(0), 4)';
CenterLatitude := oleMapInfo.Eval(MsgString);
//MapperInfo是MapInfo內部函數
3) RunMenuCommand方法—調用MapInfo菜單
利用RunMenuCommand方法可以方便的實現MapInfo的菜單功能。在MapInfo中,每一個菜單功能都對應著一個ID號,在MapBasic安裝目錄下的MENU.DEF文件中可以查詢到每個菜單對應的ID號。例如當希望客戶程序的某一個按鈕按下後彈出MapInfo的Change View對話框(對應MapInfo中Map菜單的Change View菜單項),只需要響應在這個按鈕的OnClick事件,在其中調用oleMapInfo的RunMenuCommand方法:
procere TFormMap.cmdChangeViewClick(Sender: TObject);
begin
oleMapInfo.RunMenuCommand(805);
//805是MEMU.DEF中對應M_MAP_CHANGE_VIEW的值
end;
利用同樣的方法,MapInfo的Main工具欄中對應的按鈕同樣可以集成到應用程序中。工具欄按鈕對應的ID號同樣可以在MENU.DEF中找到。
3 利用回叫機制從MapInfo中獲取信息
在集成二次開發中,通常採用回叫機制從MapInfo中獲取信息。所謂回叫,是指當集成客戶程序的MapInfo地圖窗口中有事件發生時,MapInfo通過OLE自動化對象自動向客戶應用程序發送消息的機制。
利用回調機制,在如下情況下MapInfo可以向客戶程序發送信息:
1) apInfo中執行菜單欄或者工具按鈕的命令。
2) 圖窗口發生變化。
3) MapInfo狀態條發生改變(用戶在地圖上移動滑鼠)。
而客戶程序可以接收相應的信息,在自己定義的方法中進行處理。所以可以利用回叫機制在應用程序中實現下面的功能:
1) 定義MapInfo右鍵菜單。
2) 過用戶自定義工具同MapInfo交互。
3) 控制發生變化的地圖。
4) 自定義客戶程序狀態欄顯示的內容。
回叫是利用OLE自動化集成二次開發的難點所在,其核心思想是MapInfo伺服器向客戶程序發送消息。以自定義客戶程序的狀態欄為例,回調機制的使用方法如下:
1) 建一個類,定義SetStatusText方法。此方法帶一個WideString類型的參數StatusText。這個參數是MapInfo向客戶程序傳遞過來的。
在Delphi6.0中選擇File|New|ActiveX|Automation Object,通過啟動Automation Object向導打開「Type Library」編輯器來實現。這里假設創建的類名為TmyCallBack。
2) 應用程序窗體中添加狀態欄。
3) 使用第一步中定義的類創建一個對象。
varCallBack := TMyCallBack.Create;
4)調用自動OLE對象的SetCallBack方法傳遞參數。
oleMapInfo.SetCallback(varCallBack As IMyCallBack);
5)在SetStatusText方法中處理由MapInfo傳遞的StatusText參數,控制狀態欄的顯示。
procere TMyCallBack.SetStatusText(const StatusText: WideString);
begin
MainForm.StatusBar1.Panels[0].Text := StatusText;
//MainForm是容納地圖組件的窗體
end;
4 應用實例
筆者在為某單位開發的EMC(電磁兼容)預測與分析系統中應用了OLE自動化技術,從實際應用來看,達到了滿意的效果。
系統對分布在不同站位的發射機和接收機進行電磁兼容的分析,作為其中的一個子系統,地理信息功能由Delphi 6.0和MapInfo 6.5相結合開發而成。資料庫選用MS SQL Server。應用程序主要用Delphi開發完成,當需要直觀的顯示地圖、站位、發射機、接受機、發射信號等地理信息時調用MapInfo的功能來實現。利用OLE自動化技術實現二者的交互。
站位坐標、參數,發射機接受機參數、所在站位等信息存儲在SQL Server的表中。首先利用一個MapBasic程序連接SQL Server資料庫,獲取信息存入MapInfo的表中,載入基本地圖並為站位、發射機、接受機、信號等分別創建圖層。
Delphi首先啟動MapInfo伺服器,然後運行MapBasic程序載入地圖,接著通過OLE自動化和MapInfo伺服器交互。系統結構如下圖所示:
系統運行界面如下:
其中
隱藏、顯示圖層由oleMapInfo的do方法調用MapBasic語句實現。
放大、縮小、漫遊按鈕由oleMapInfo的RunMenuCommand方法實現。
試圖設置中獲取地圖中心坐標通過oleMapInfo的Eval方法實現。
狀態欄的更新通過OLE回叫實現。
5 結束語
實踐表明,利用OLE自動化技術開發MapInfo應用程序節省了開發周期,能有靈活有效的控制MapInfo,實現MapInfo的地理信息系統功能。它的缺點是需要在後台調用MapInfo故程序運行速度受到限制。然而在MapX控制項應用成熟以前,OLE調用、回叫仍然將會是普遍應用的開發方法。
Ⅳ VB 與MapInfo 二次開發的重點
( 1) MapInfo 對象的創建
本系統使用 OLE Automation 技術在 VB 中創建一個 MapInfo 的應用對象,然後在 VB環境下對該對象進行操作 ( 張峰等,2004) 。首先在 VB 環境下聲明一個對象變數如 Map-Info,接著在 VB 中使用 CreateObject ( ) 函數創建一個 MapInfo 對象,使用語句:
Set MapInfo = CreateObject( 「MapInfo. Applicaiton」)
要連接一個已運行著的 MapInfo,需要用 Visual Basic 的 GetObject ( ) 函數。
Set MapInfo = GetObject( 「MapInfo. Application」)
由於該語句創建的是 MapInfo 應用對象,所以在本地機器系統中應該有 MapInfo 軟體平台,否則將產生錯誤,不能創建 MapInfo 應用對象。集成地圖開發是在程序中通過調用語句來在後台啟動 MapInfo。創建完對象後就可以在 VB 環境里使用對象 MapInfo 的屬性和方法,通過 VB 的對象瀏覽器,可以看到 MapInfo 對象的屬性和方法,最常用的是 do 方法。MapInfo 應用對象 do 方法識別和執行字元串命令行。由於在 MapInfo 系統中包含的庫文件 「MapBasic. def」以及 「Menu. def」中集成了許多命令函數,使 MapInfo 的有些功能往往只需要一兩條語句就可以在 VB 中完成,使用起來也比較簡單、方便。
( 2) VB 評價結果在 MapInfo 中的圖形顯示和重畫
在 GIS 軟體系統中,圖形的顯示及重畫功能是系統自動完成的,可是由於本系統是採用 OLE 技術,將 MapInfo 系統集成到 VB 的環境中,則圖形的顯示和重畫只能在 VB 的環境里完成,由於 VB 自身無法識別 MapInfo 的圖形格式,所以就無法進行圖形的顯示與重畫。使用 Map Basic 語句「Set Application Window」來讓 MapInfo 的對話框和錯誤信息窗口從屬於客戶程序。「Set Next Document」語句允許 「再生」窗口。在 VB 與 MapInfo 集成環境里,圖形的顯示可以使用 MapInfo 的窗口來實現,也可以在 VB 的窗口中實現,MapInfo允許以三種模式將一個地圖在 VB 環境里顯示。其中 style 1: 表示無模式形式,即地圖將充滿整個 VB 窗體中,就像將 MapInfo 的圖形貼在 VB 窗體上一樣 ( 張峰等,2004) ; style2: 則表示生成帶半高標題欄的彈出式窗口 ( 像 MapInfo 的圖例窗口) ; style 3: 產生帶全高標題欄的窗口。後兩種方式,都不能使窗口圖形窗口最大和最小化,這給用戶的操作帶來不便,同時也不符合 Windows 系統風格。因此本系統採用 style 1 模式。
MapInfo 允許在 VB 的窗體上顯示圖形,使用命令:
「Set Next document parent」& Form1. hWnd &「style 1」
Form1 是 VB 中的一個用來顯示圖形的窗體。在 VB 環境里打開 MapInfo 的地圖和數據表格。但還存在一些問題,當 VB 窗口最大化時,MapInfo 圖形不能重畫,即當用戶改變地圖窗口大小時,MapInfo 並不會依據新窗口的大小自動重新設置地圖內容以添滿窗口。為此必須利用 Windows API 函數 MoveWindow 編寫代碼來實現,使每一次窗體的大小變化時,地圖均重畫。
( 3) 報表輸出
通過讀取資料庫中存儲的評價信息,按照相應的格式調用到相應的報表位置,生成報表,如圖 7. 9 所示。關鍵點是讀取資料庫和列印,下面是讀取資料庫及列印代碼:
圖 7. 9 報表輸出列印界面
Straql = 」select* from pingjia where name = 」』& text1. text &』」」
ExecuteSql( Strsql)
Me. PrintForm
Ⅵ 如何用VC++調用MapInfo
VC++的話要用MapX
Ⅶ 一個關於Mapinfo數據和資料庫的問題
1 Callback
在我們的程序中集成MapInfo應用後,MapInfo能夠自動地向客戶程序發送信息。例如,在應用程序中,當地圖窗口發生變化時,MapInfo將調用客戶端程序通知發生變化的窗口的句柄。當發生某一事件導致MapInfo調用客戶端程序的這種方法稱為Callback(回調)。
在下列情況中,Callback允許MapInfo發送消息給客戶應用程序:
·用戶使用定製工具與MapInfo窗口進行交互
例如,用戶點擊並拖動滑鼠在MapInfo的地圖窗口上畫線時,MapInfo能夠把用戶選擇的各點坐標消息發送給應用程序。
·用戶選擇菜單命令
例如,如果應用程序定製了MapInfo的快捷菜單(即用戶右擊時彈出的菜單),當用戶從快捷菜單中選擇了定製的命令後,MapInfo就會把這個菜單事件通知給應用程序。
·地圖窗口發生變化
當用戶改變地圖窗口內容(如添加或刪除圖層,平移地圖時),MapInfo就會將發生變化的窗口句柄告知應用程序(這類似於apasic自身的句柄過程:WinChangedHandler。)�
·MapInfo中狀態欄的內容發生變化
2 在P中實現MapInfo的callback
為了使用MapInfo的callback,應用程序必須能作為DDE伺服器或OLE自動化伺服器。VC++,V,Delphi等開發工具對OLE自動化服務的支持都很好,開發起來很方便。但P對OLE自動化服務的支持不夠理想,筆者和周圍的許多同行試了很多方法都未能實現Callback。是不是在P里就不能使用MapInfo的Callback呢?通過查閱了大量的文獻,終於找到了一個方法實現了Callback。其原理如圖1所示。
圖1 在P中實現MapInfo的callback的原理圖
實現步驟如下:
打開P的庫畫板,新建一個P庫並命名為Ole[CD#*3]Callack.pbl;定義一個立即數變數:integer handle;在庫中創建一個不可見自定義用戶對象:nuo[CD#*3]Callack,為其添加用戶對象函數:public subroutine uf[CD#*3]ini(integer Whnd),無返回值。�
在其腳本中添加代碼如下:
handle=Whnd
如果要將MapInfo狀態欄的信息反映到客戶應用程序的狀態欄上,則要添加一個名為SetStatusText用戶對象函數,只有一個字元串型(string)的參數。當每次地圖窗口發生變化時,需要MapInfo通知應用程序,就要添加一個名為WindowContentsChanged用戶對象函數,只有一個四位元組整型(integer)的參數。當自定義菜單項或自定義按鈕被使用時,如果需要MapInfo通知應用程序,就要添加一個名為與自定義菜單項或自定義按鈕的過程名相同的用戶對象函,只有一個字元串型(string)的參數。限於篇幅,我們在這里僅添加名為WindowContentsChanged用戶對象函數,參數為:integer asresponse,無返回值。
在其腳本中添加代碼如下:
send(handle,1024,0,as_response)/*向句柄號為handle的窗口發送系統消息為pbm_custom01的消息,並把as_response也發送過去*/
保存庫文件並編譯成P運行時鏈接庫Ole_Callack.pbd,這是關鍵所在。我們的第一階段工作就完成了,在後面的工作中我們要使用這個鏈接庫。
在P的庫畫板再新建一個名為Callack_Test.plb的P庫,新建一個DI窗口w_main和一個用作w_main的sheet窗口w_sheet。
為w_main新增一個用戶自定義事件:ue_MapInfoWCHnd事件號為pbm_custom01,用以接收MapInfo發來的窗口句柄。
在w_main的open事件中編寫代碼如下:
openSheet(w_sheet,w_main)
在w_main的ue_MapInfoWCHnd事件中編寫代碼如下:
messagebox(「回調測試」,「MapInfo返回的地圖窗口發生變化的窗口
句柄為:」+string(as response))
在w_sheet的open事件中編寫代碼如下:
OleObject myPOleObject
myPOleObject=create OleObject/*創建Poweruilder OLE自動化服務對象*/
int Errcode
ErrCode=myPOleObject.ConnectToNewObject(「Poweruilder.Application」)
If ErrCode<>0Then
Messageox(「錯誤」,「連接Poweruilder伺服器錯誤,退出。」)
Halt Close
end if
/*這就是我們前面編譯好的鏈連庫Ole[CD#*3]Callack.pbd的完整路徑*/
myPOleObject.LibraryList=「c:\Callack.pbd」
myPOleObject.achineCode=False /*如果你編譯成的是機器碼就用True,這里是False*/
OleObject UserOleObject /*創建用戶自定義OLE對象*/
UserOleObject=Create OleObject
/*鏈接到不可見自定義用戶對象:nuo_Callack*/
UserOleObject=myPOleObject.CreateObject(「nuo_Callack」)
if isNull(UserOleObject)then
messagebox(「沒有對象」,「不能創建對象UserOelObject」)
halt close
end if
myPOleObject.uf_int(handle(w[CD#*3]main)/*把主窗口的句柄傳遞給用戶自定義OLE對象*/
OLEObject IOleObject
IOleObject=Create OLEObject
/*連接MapInfo OLE伺服器*/
ErrCode=IOleObject.ConnectToNewObject("MapInfo.Application")
If ErrCode<>0Then
Messageox(「連接錯誤」,「連接地圖伺服器錯誤,在使用本程序前要安裝MapInfo軟體。」)� Halt
End If
/*把我們的自定義OLE對象傳遞給MapInfo OLE對象的Callack*/
IOleObject.SetCallack(UserOleObject)
/*重新定向MapInfo的地圖窗口到w_sheet上*/
IOleObject.Do(「Set Next Document Parent」+String(Handle(this))+「Style 1」)� IOleObject.Do(′Set.Application Window′+String(Handle(this)))
/*打開MapInfo地圖並在w_sheet上顯示*/
IOleObject.DO(′run application"c:\maptest.wor"′)
編譯執行。改變地圖窗口的大小或圖層,w_main主窗口將會接收到MapInfo發來的消息,將會彈出我們前面的消息窗口顯示發生變化地圖窗口的句柄,將它替換成相應的代碼就可以進行相應的處理了。
3 說 明
本程序在Poweruilder 6.5下編譯測試通過,在MapInfo Professional 4.0、MapInfo Professional 4.5和MapInfo Professional 5.0環境下均運行良好。
4 結 論
P對OLE自動化服務的支持並沒有VC,V,Delphi等開發工具的支持強大,我們只好採用迂迴策略,定製一個P用戶自定義OLE對象用來作MapInfo的OLE調用,再把自定義OLE對象接收到的消息發送給我們的應用程序,從而實現了P與MapInfo的交互,進而用這個方法開發出功能完善的大型GIS資料庫應用程序。