在利用ArcGIS二次开发实现“鹰眼”功能时发现在MapControl控件不能自动添加控件事件(OnMapReplaced、OnExtentUpdated等)。咨询ESRI支持中心后给出的回答是:
“在ArcGIS 10.0之后对于MFC框架的支持出现了一些障碍,导致ArcGISEngine中的ActiveX控件无法注册。”
既然这样那么我们就动手自己添加我们所需的响应函数。
我的开发平台是:VS2010(MFC)+ArcGIS10.1
第一步:我们要得到事件响应函数的函数名、参数列表、以及控件给这个函数分配的ID
方法使使用VS带的开发工具OLE View,打开esriControls.olb,定位到IMapControlEvents2,我们就可以看到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_MAP、BEGIN_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中正确书写事件响应,那么程序都能顺利进入事件响应函数中,但是在执行完事件响应函数后会出现指针错误。
附半成品图: