您的位置:首页 > 编程语言 > C语言/C++

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

2012-07-23 21:47 525 查看

3.MapX在VC++ 环境下GIS基本功能的实现

在进行MapX 开发之前,确保已经在计算机中正确的安装了MapX 控件。下面就用一个具体的实例,介绍在VC+ +中集成MapX 的方法。

3.1 将MapX支持类库加入工程

在您的项目中包括MapX.cpp和.h文件。这两个文件包含用于对MapX控件进行访问的类定义和方法实现。MapX.h 和 MapX.cpp 文件可能位于安装有 MapX 的 Samples50CPP 子目录中(如果您安装的事MapX 4.0,则路径为 … Samples40C++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提供的可用标准工具如下表。

工具
常数
说明
添加线条

miAddLineTool
将线条图元添加到插入图层中。

添加点

miAddPointTool
单击该工具可将点图元添加到插入图层中。

添加折线

miAddPolyLineTool
将折线图元添加到插入图层中。

添加区域

miAddRegionTool
将区域图元添加到插入图层中。

箭头

miArrowTool
单击标题或注释此外,在可编辑图层中移动选定图元或调整选定图元的大小。

居中

miCenterTool
单击该工具可以重新将地图居中。

加标签

miLabelTool
在一个图元上单击可以给该图元加标签。

平移

miPanTool
拖动该工具可以重新将地图居中。

多边形选择

miPolygonSelectTool
单击该工具可以绘制一个多边形;该多边形内的对象将被选定。

半径选择

miRadiusSelectTool
拖动该工具可以选择半径内的图元。

矩形选择

miRectSelectTool
拖动该工具可以选择矩形内的图元。

选择工具

miSelectTool
单击该工具可以选择图元。

符号

miSymbolTool
放置符号注释。

文本

miTextTool
放置文本注释。

放大

miZoomInTool
放大。

缩小

miZoomOutTool
缩小。

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 %sn",

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 feature

CMapXFeatureftr = ftrs.Item(1);

// get the style object from the feature

CMapXStylestyle = ftr.GetStyle();

style.SetRegionBackColor(255);

// update the feature in the layer

ftr.Update();

}

catch (COleDispatchException *e) {

e->ReportError();

e->Delete();

}

catch (COleException *e) {

e->ReportError();

e->Delete();

}

}

// place a new symbol at the point clicked on

else 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 feature

ftr.SetType(miFeatureTypeSymbol);

// Get the point object from the feature

// and call the Set method

ftr.GetPoint().Set(X1, Y1);

// Add it to the layer

layers.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 %sn",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 button

CMenu 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();

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: