手动添加MapControl中的消息响应函数

时间:2022-12-19 21:04:48

    在利用ArcGIS二次开发实现“鹰眼”功能时发现在MapControl控件不能自动添加控件事件(OnMapReplacedOnExtentUpdated等)。咨询ESRI支持中心后给出的回答是:

“在ArcGIS 10.0之后对于MFC框架的支持出现了一些障碍,导致ArcGISEngine中的ActiveX控件无法注册。”

    既然这样那么我们就动手自己添加我们所需的响应函数。

    我的开发平台是:VS2010MFC+ArcGIS10.1

第一步:我们要得到事件响应函数的函数名、参数列表、以及控件给这个函数分配的ID

方法使使用VS带的开发工具OLE View,打开esriControls.olb,定位到IMapControlEvents2,我们就可以看到MapControl所有的事件响应函数:

手动添加MapControl中的消息响应函数

 手动添加MapControl中的消息响应函数

下面我们要在*.h文件中加入事件响应函数的声明:

DECLARE_EVENTSINK_MAP()

void OnMouseDown( long button, long shift,  long X, long Y,double mapX, double mapY);

 

*.cpp文件中加入事件响应函数的定义:

void CMyGIS02View::OnMouseDown( long button, longshift,  long X, long Y,double mapX,double mapY)

{

//事件响应代码

}

重要的,我们要在*.cpp文件中添加事件接收响应

BEGIN_EVENTSINK_MAP(CMyGIS02View, CFormView)

ON_EVENT(CMyGIS02View, IDC_MAPCONTROL1,1,CMyGIS02View::OnMouseDown,VTS_I4 VTS_I4 VTS_I4 VTS_I4 VTS_R8 VTS_R8)

END_EVENTSINK_MAP()

注意BEGIN_EVENTSINK_MAPBEGIN_MESSAGE_MAP的区别,前者应用于COM组件的事件链接点的,后者应用于窗口的消息循环。

ON_EVENT( theClass,id,dispid,pfnHandler,vtsParams)

解释一下ON_EVENT中的第3个参数与第5个参数,

dispid

Thedispatch ID of the event fired by the control.

OLE VIEW中函数位于第一个位置,那么这里dispid=1

vtsParams

Asequence of VTS_ constants that specifiesthe types of the parameters for the event. These are the same constants thatare used in dispatch map entries such asDISP_FUNCTION.

一系列用来指定事件参数类型的VTS_常量。在MSDN中搜索EVENT_CUSTOM会得到VTS_常量与参数类型的对照表。其中:

VTS_I4

long

VTS_R8

double

 

这样我们就成功的添加了OnMouseDown()这个函数。

但是在添加OnMapReplaced()事件时却出现了问题,程序进入不到事件响应函数亦或进入事件响应函数后系统崩溃(内存读取错误,向空指针写入数据)

OLE VIEW中事件响应函数声明:

void OnMapReplaced(VARIANT newMap);

进过反复试验,错误原因在于类型为VARIANT的参数。在VTS_常量与参数类型的对照表中没有和VARIANT对应的常量(见下表),因此我们只能进行适当的变通。

VTS_VARIANT

const VARIANT*

VTS_PVARIANT

VARIANT*

具体做法如下:

BEGIN_EVENTSINK_MAP(CMyGIS02View, CFormView)

ON_EVENT(CMyGIS02View, IDC_MAPCONTROL1,15,CMyGIS02View::OnMapReplaced,VTS_VARIANT)

END_EVENTSINK_MAP()

 

void CMyGIS02View::OnMapReplaced(VARIANT*newMap)

{

//向鹰眼MapControl控件加载地图 [2/26/2014 pan]

m_MapControl2->LoadMxFile(CComBSTR("G:\\gis_ex09\\ex01\\ex01.mxd"));

}

要注意我们在事件接收响应中使用的是VTS_VARIANT常量,使用VTS_PVARIANT无法进入事件响应函数

OnMapReplaced的声明和定义中要把形参VARIANT newMap改为VARIANT*newMap,否则程序执行完事件响应后程序会崩溃

实际上无论事件响应函数中的参数列表怎么写,只要ON_EVENT中正确书写事件响应,那么程序都能顺利进入事件响应函数中,但是在执行完事件响应函数后会出现指针错误。

 

附半成品图:

手动添加MapControl中的消息响应函数

手动添加MapControl中的消息响应函数