近期使用MapX控件做了一個GIS項目,因爲是在QT中使用,所以用dumpcpp生成了QT下可用的代碼,做了一些修改之後,代碼在QT中正常運行。
後來客戶提出新的需要,要求顯示地圖經緯度,但是因爲地圖上圖元移動使用的單位是公里,所以之前把地圖的NumericCoord的單位設置爲了miUnitKilometer,而Mapx並不支持兩種座標系統同時使用。
初期的思路如下:
1.監聽鼠標移動事件,獲取到屏幕座標XY
2.將屏幕座標XY轉換爲地圖座標,單位爲公里
3.將公里轉換爲經緯度
問題主要出現在第二步,調用MapX的ConvertCoord時,提示Type MisMatch,函數原型爲
void ConvertCoord(double& ScreenX, double& ScreenY, double& MapX, double& MapY, int Direction);
參數給的也是正確的,使用DynamicCall之後仍然出現同樣的錯誤。無奈之下,參照QT的源碼,直接使用queryInterface獲取IDispatch接口,用IDispatch的Invoke接口調用,仍然提示Type Mismatch錯誤。
後來查看了下VC的Mapx的cpp文件,發現裏面代碼如下:
void CMapX::ConvertCoord(float* ScreenX, float* ScreenY, double* MapX, double* MapY, short Direction)
{
static BYTE parms[] =
VTS_PR4 VTS_PR4 VTS_PR8 VTS_PR8 VTS_I2;
InvokeHelper(0x22, DISPATCH_METHOD, VT_EMPTY, NULL, parms,
ScreenX, ScreenY, MapX, MapY, Direction);
}
使用的是InvokeHelper函數,再查一下,發現COleDispatchDriver有InvokeHelper成員,引入了MFC庫後,COleDiapatcherDriver綁定IDispatch接口,調用InvokeHelper後,調用成功,終於解決了activex控件在QT中的最麻煩的問題,我看stackoverflow上也有很多類似的問題,大多是採用dynamicCall+QVariantList的調用方式,但是那種方式並沒有解決我的問題。
QT實現的Activex兼容技術還是有缺陷的,適當的時候還是需要引入原生的COM來進行activex控件方法的調用,不能超出了QT平臺之外,就束手無策了。
最後貼上代碼:
IDispatch* map_itf = NULL;
map_ctrl_->queryInterface(IID_IDispatch,(void**)&map_itf);
if(map_itf)
{
COleDispatchDriver driver(map_itf,FALSE);
static BYTE parms[] =
VTS_PR4 VTS_PR4 VTS_PR8 VTS_PR8 VTS_I2;
driver.InvokeHelper(0x22, DISPATCH_METHOD, VT_EMPTY, NULL, parms,
&screen_x, &screen_y, &map_x, &map_y, miScreenToMap);
}