用VC++对MapX进行二次开发总结

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

用VC++对MapX进行二次开发总结(二)
1839发表评论查看评论3.MapX在VC++ 环境下GIS基本功能的实现
在进行MapX 开发之前,确保已经在计算机中正确的安装了MapX 控件。

下面就用一个具体的实例,介绍在VC+ +中集成MapX 的方法。

3.1 将MapX支持类库加入工程
在您的项目中包括MapX.cpp和.h文件。

这两个文件包含用于对MapX控件进行访问的类定义和方法实现。

MapX.h 和 MapX.cpp 文件可能位于安装有 MapX 的 Samples50\CPP 子目录中(如果您安装的事MapX 4.0,则路径为…\ Samples40\C++\Cpp)。

利用VC++ 环境下的应用程序生成向导创建一单文档应用程序MapSample。

将MapX.h和MapX.cpp文件拷贝到当前工程路径下,然后从Project菜单中选择Add to Project >Files命令,此时打开Insert Files into Project对话框,选择MapSample文件夹下的MapX.h和MapX〉cpp文件加入到工程中。

警告:不要选择Project菜单中的Add to Project > Components And Controls命令。

这样做将会创建一个.cpp文件,但该文件将是不完整的。

我一开始就是这么做的,结果很多常用函数都没有,郁闷了我很长时间。

希望大家一起要切记这一点。

3.2 使用VC++创建MapX控件
在将包含该控件得视图中包括它:
#include “MapX.h”



Class CMapXSampleView : public CView
{:::Protected:CMapX m_ctrlMapX;::}
要声明表示用于MapX的控件ID的常数:
(1)选择“View”>”Resource Symble”。

(2)单击“New”。

(3)键入“IDC_MAP”来作为名称。

要在类向导中为WM_SIZE和WM_CREATE消息创建处理程序:
(1)转入”View”>”ClassWizard”;
(2)从“Class Name”组合框中选择您的视图类。

(3)在“Messages”列表框中,单击“WM_CREATE”,然后单击“Add Function”。

(4)接着还在该消息框中选择” WM_SIZE”并单击“Add Function”。

(5)然后,单击“Edit Code”
在创建视图时创建该控件。

在CMapXSampleView::OnCreate中:
//create map with default size
//resize message will cause it to be size to the client area of the view
If(!m_ctrlMapX.Create(NULL,WS_VISIBLE, CRect(0,0,100,100),this,IDC_MAP))
Returen -1;
Keep the control’s size in sync with the containing window;
//resize the map to be the same size as our client area
Void CMapXSampleView:: OnSize(UINT nType, int cx, int cy)
{CView::OnSize(nType, cx, cy);if(cx!=0 && cy!=0)m_ctrlMapX.MoveWindow(0,0,cx,cy);}
像您为WM_CREATE消息所作的一样为WM_SETFOCUS消息创建新消息标头。

在我们的示例中,我们想要确保只要窗口被激活MapX就获得焦点:
void CMapXSampleView::OnSetFocus(CWnd* pOldWnd)
{CView::OnSetFocus(pOldWnd);m_ctrlMapX.SetFocus();}
3.3 使用地图标准工具
在地图显示出来后,用户通常要以各种比例查看地图的全局、局部或细部,必须提供诸如放大、缩小和漫游等功能。

采用MapX通用工具,可以非常方便地实现上述功能。

设定MapX使用标准工具的方法很简单,只需设定地图对象的CurrentTool属性。

下面的例子是用标准放大工具实现放大功能。

添加新菜单项资源,输入标题“工具”,在“工具”下添加子菜单,输入标题“放大”及ID 为ID_ZOOM_ IN。

打开类向导,选择视图类CMapXSampleView,为菜单项ID_ZOOM_IN 添加COMMAND 消息映射函数OnZoomIn ( ),并编辑码如下。

void CMapXSampleView::OnZoomIn()
{m_ctrlMapX.SetCurrentTool(miZoomInTool);// miZoomInTool为放大工具常量}
编译运行程序,选择“工具|放大”,就会看到此时光标变为放大镜,单击鼠标就会实现放大功能。

可用相同方法实现其他标准工具的功能。

MapX提供的可用标准工具如下表。

3.4 使用自定义工具
MapX提供的地图标准工具能满足一般需要,但在一些特殊地方,用户可能需要某种特殊工具来完成某些特定的地图操作功能。

因此,MapX提供了用户自定义工具的方法,这样可以大大扩展MapX的应用范围。

开发者可使用地图对象的CreateCustomTool 方法创建自定义工具。

一旦您已使用CreateCustomTool方法创建了定制工具后,就可以在用户使用定制工具时使用ToolUsed事件执行操作。

此示例进行测试以了解正使用哪一工具。

然后,根据正在使用的工具,该示例或者:
•更改光标下的地图图元的样式,或者
•在用户单击处放置新符号。

void CMapXSampleView::OnToolUsed(short ToolNum, double X1, double Y1, double X2, double Y2, double Distance,BOOL Shift, BOOL Ctrl, BOOL* EnableDefault)
{CString str;CMapXPoint pnt;str.Format("Tool=%d, [%f,%f] [%f, %f], dist=%f, %s %s\n",
ToolNum, X1,Y1,X2,Y2,Distance, (Shift)?"Shift":"",(Ctrl)?"Ctrl":"");TRACE(str);
// change the style of the feature under the cursor
if (ToolNum == MAP_TOOL_CHANGESTYLE) {try {// Need the dispatch to use the point
if (pnt.CreateDispatch(pnt.GetClsid())) {pnt.Set(X1, Y1);}
else {// something went wrong, can't use the point...
AfxThrowOleException(CO_E_CLASS_CREATE_FAILED);}
CMapXLayers layers = m_ctrlMapX.GetLayers();
// Get the USA feature under the cursor
CMapXFeatures ftrs =layers.Item("USA").SearchAtPoint(LPDISPATCH(pnt));
// work on only the first featureCMapXFeatureftr = ftrs.Item(1);
// get the style object from the featureCMapXStylestyle = ftr.GetStyle();
style.SetRegionBackColor(255);// update the feature in the layerftr.Update();}
catch (COleDispatchException *e) {e->ReportError();e->Delete();}
catch (COleException *e) { e->ReportError();e->Delete();}}
// place a new symbol at the point clicked onelse if (ToolNum == MAP_TOOL_NEWPOINT) {try
{CMapXLayers layers = m_ctrlMapX.GetLayers();CMapXFeatureftr;
// Need the dispatch id to use the feature if (ftr.CreateDispatch(ftr.GetClsid())) {
// Symbol featureftr.SetType(miFeatureTypeSymbol);
// Get the point object from the feature
// and call the Set methodftr.GetPoint().Set(X1, Y1);
// Add it to the layerlayers.Item("USA").AddFeature(ftr);} else {
AfxThrowOleException(CO_E_CLASS_CREATE_FAILED);}}catch (COleDispatchException *e) {
e->ReportError();e->Delete();}catch (COleException *e) {e->ReportError();e->Delete();}}}
3.5 处理MapX事件
若要处理MapX事件,您首先需要为感兴趣的事件建立eventsink地图。

用于事件DISPATCH id 的常数是在MapX.h中为MapX定制事件定义的,并且是在中为 OLE 普通事件定义的。

// From MapX.h
#define MAPX_DISPID_SELECTION_CHANGED 0x1
#define MAPX_DISPID_RESOLVEDATABIND 0x2
#define MAPX_DISPID_TOOLUSED 0x3
#define MAPX_DISPID_REQUESTDATA 0x4
#define MAPX_DISPID_DATAMISMATCH 0x5
#define MAPX_DISPID_MAPVIEWCHANGED 0x6
#define MAPX_DISPID_ANNOTATIONADDED 0x7
#define MAPX_DISPID_ANNOTATIONCHANGED 0x8
#define MAPX_DISPID_THEMEMODIFYREQUESTED 0x9
#define MAPX_DISPID_DRAWUSERLAYER 0x0a
#define MAPX_DISPID_POLYTOOLUSED 0x0b
// From
#define DISPID_CLICK (-600)
#define DISPID_DBLCLICK (-601)
#define DISPID_KEYDOWN (-602)
#define DISPID_KEYPRESS (-603)
#define DISPID_KEYUP (-604)
#define DISPID_MOUSEDOWN (-605)
#define DISPID_MOUSEMOVE (-606)
#define DISPID_MOUSEUP (-607)
#define DISPID_ERROREVENT (-608)
EVENT_SINK中的ON_EVENT 宏也为MapX控件指定一个ID (在该示例中为 IDC_MAP),指定该事件的参数,并且指定事件处理程序方法的名称。

在视图标头文件MapXSampView.h中,将“DECLARE_EVENTSINK_MAP ()”一行放置于“DECLARE_MESSAGE_MAP”行之下。

从CMapXSampleView.cpp:
BEGIN_EVENTSINK_MAP(CMapXSampleView, CView)
ON_EVENT(CMapXSampleView, IDC_MAP, DISPID_MOUSEMOVE,
OnMouseMoveInMap,VTS_I2 VTS_I2 VTS_XPOS_PIXELS VTS_YPOS_PIXELS)
ON_EVENT(CMapXSampleView, IDC_MAP, MAPX_DISPID_MAPVIEWCHANGED,
OnMapViewChanged, VTS_NONE)
ON_EVENT(CMapXSampleView, IDC_MAP, DISPID_MOUSEUP,
OnMouseUpInMap, VTS_I2 VTS_I2 VTS_XPOS_PIXELS VTS_YPOS_PIXELS)
ON_EVENT(CMapXSampleView, IDC_MAP, MAPX_DISPID_TOOLUSED,
OnToolUsed, VTS_I2 VTS_R8 VTS_R8 VTS_R8 VTS_R8 VTS_R8 VTS_BOOL
VTS_BOOL VTS_PBOOL)
ON_EVENT(CMapXSampleView, IDC_MAP,
MAPX_DISPID_THEMEMODIFYREQUESTED, OnThemeModifyRequested,
VTS_DISPATCH)
END_EVENTSINK_MAP()
随后是用于OnToolUsed 事件的事件处理程序代码。

来自CMapXSampleView.h 的声明:
void OnToolUsed(short ToolNum, double X1, double Y1, double X2,double Y2, double
Distance, BOOL Shift, BOOL Ctrl, BOOL* EnableDefault);
…以及来自CMapXSampleView.cpp 的实现方式(我们只使用 TRACE 宏将参数输出到调试窗口):
void CMapxSampleView::OnToolUsed(short ToolNum, double X1, double Y1,
double X2, double Y2, double Distance, BOOL Shift, BOOL Ctrl, BOOL* EnableDefault)
{CString str;
str.Format("Tool=%d, [%f,%f] [%f, %f], dist=%f, %s %s\n",ToolNum, X1,Y1,X2,Y2,Distance,
(Shift)?"Shift":"",(Ctrl)?"Ctrl":"");TRACE(str);}
3.6 添加快捷菜单
DISPID_MOUSEUP事件可用于添加快捷(鼠标右键按钮)菜单。

为您的快捷菜单创建菜单资源(如果菜单资源的ID为
IDR_CONTEXTMENU)。

OnMouseUpInMap 处理程序类似于以下代码:
// if right mouse button, display the context menu
BOOL CMapxSampleView::OnMouseUpInMap(short Button, short Shift,
OLE_XPOS_PIXELS x,OLE_YPOS_PIXELS y)
{if (Button == 2) { // right buttonCMenu menu; // top-level menu
CMenu *pMenu=NULL; // pop-up menu// Load the menu resource.
menu.LoadMenu(IDR_CONTEXTMENU);// TrackPopupMenu cannot display the top-level menu, so get
// the handle of the first pop-up menu.pMenu = menu.GetSubMenu(0);if (!pMenu) {return TRUE;}
SetMenuDefaultItem(pMenu->m_hMenu, ID_VIEW_PROPERTIES,FALSE);
// Display the floating pop-up menu. Track the right mouse
// button on the assumption that this function is called
// during WM_CONTEXTMENU processing.POINT pt;GetCursorPos(&pt);
pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON,pt.x, pt.y, this, NULL);
// Destroy the menu.menu.DestroyMenu();}return TRUE;}
3.7 MapX异常错误处理
MapX通过报告(引发)COleDispatchException 来报告大多数错误。

在调用 MapX 时捕获异常错误是十分重要的,因为MFC的默认异常错误处理程序不捕获它们并且您的应用程序将退出。

在消息框中显示对错误的说明也是非常有用的。

错误消息的文本将帮助您确定是否正确使用了 MapX 图元,或者是否已发生某一其它问题。

COleDispatchException类还在公共成员m_wCode中包括错误代码,以便您的程序可以标识和处理不同类型的错误。

对于错误代码及其说明的列表,请参见联机帮助中的 MapX 错误代码。

如果在尝试调用MapX时具有一般的OLE错误(在您使用过时的MapX.h 或 MapX.cpp 版本时可能发生),则 MFC 将引发COleException。

建议你在调用 MapX 时捕获全部两个异常错误类型。

MapX 也可能在 Error 事件中传递错误(尽管非常少见)。

只有在不从MapX属性或方法直接调用的异步处理(像redraw)期间出现某种类型的错误时,才可能发生上述情况。

在此示例的 ThemeModifyRequested 事件的事件处理程序中,我们显示普通的“主题”属性对话框以让用户更改主题颜色等。

请注意异常错误处理的方式。

// Note: in objects passed to events, the event handler
// does not change the reference count
// ie: do not call release on the object
void CMapxSampleView::OnThemeModifyRequested(LPDISPATCH Theme)
{try {CMapXTheme theme;COptionalVariant vHelpFile, vHelpID;
// mark as optional since we don't have a helpfile
theme.AttachDispatch(Theme, FALSE); // don't auto release
theme.ThemeDlg(vHelpFile, vHelpID);
// could decide to bring up legend dlg here instead
//CMapXLegend leg(theme.GetLegend());
//leg.LegendDlg(vHelpFile, vHelpID);}
catch (COleDispatchException *e) { e->ReportError();e->Delete();}
catch (COleException *e) {e->ReportError();e->Delete();}}。

相关文档
最新文档