目前基于MO的开发实例以VB居多,VC实例只有MFC目录下自带一些例子。这里给出了几个常见问题的示例代码,希望对刚接触MO的广大VC二次开发人员有所帮助。
基础的入门教程可以参考下面的网址:
http://www.esrichina-bj.cn/library/chinanews/new11/news11-mo.htm
目 录
1.为Shape指定Symbol。
2.生成一个线对象的示例
3.为何我画了对象却没有显示?
4.已经获得part,如何组装成Line?
5.获得线的起点、终点的方法。
6.对所有图层依次执行某个操作的示例代码:
7.利用ValueMapRenderer为同一图层N个多边形着色
8.制作一个点图层(转载)
9.改变图层颜色(转载)
10.Fields不能通过索引号来获取Field,怎么办?
11.判断图层类型是点、线还是面图层。
12.在指定的目录下保存全部图层文件。(转载)
13.如何合并两个图层?(转载)
--------------------------------------------------------------------------------
1.为Shape指定Symbol
演示代码如下:
--------------------------------------------------------------------------------
{
CMoSymbol sym;
if (!sym.CreateDispatch("MapObjects2.Symbol"))
return;
sym.SetColor(moPurple);
sym.SetSymbolType(moLineSymbol); //常量定义请见MapObjects2.h
sym.SetStyle(moSolidLine);
sym.SetSize(2);
m_map.DrawShape(line, sym);
m_map.Refresh();
}
--------------------------------------------------------------------------------
2.生成一个线对象的示例
演示代码如下:
--------------------------------------------------------------------------------
{
CMoLine line;
line.CreateDispatch("MapObjects2.Line");
CMoPoints pts;
pts.CreateDispatch("MapObjects2.Points");
CMoPoint pt;
pt.CreateDispatch("MapObjects2.Point");
pt.SetX(1);
pt.SetY(1);
pts.Add(pt);
pt.SetX(100);
pt.SetY(100);
pts.Add(pt);
CMoParts parts(line.GetParts());
parts.Add(pts);
}
--------------------------------------------------------------------------------
3.为何我画了对象却没有显示
1,检查图层是否layer.SetVisible(TRUE);
2,检查map的extent是否包含了你所需要显示的对象。关于这个可以参考6中的代码,它通过遍历所有图层,获得了一个最合适的Extent
3,检查该对象是否被其他对象覆盖。
4,检查该对象是的颜色是否与背景相同。
4.已经获得part,如何组装成Line:
演示代码如下:
--------------------------------------------------------------------------------
int DEF_P0017(CMoLine* pline)
{
CMoParts parts = pline->GetParts(); //get parts
for(short i=0; i< parts.GetCount(); i++){
CMoPoints P1( parts.Item(COleVariant(i))); //parts-->points
CMoLine Line; //create line object
if (!Line.CreateDispatch(TEXT("MapObjects2.Line"))){
return 1;
}//end if
CMoParts ps(Line.GetParts()); //get line's parts
ps.Add(P1); //add pline --> parts -->points-->Line
}//end for
return 0;
}
--------------------------------------------------------------------------------
5.获得线的起点(从某种意义上将,也是终点)的方法。
Here's some sample code that assumes that there is at least two points in the line:
演示代码如下:
--------------------------------------------------------------------------------
/*** START CODE ***/
//track the line
CMoLine myLine(TrackLine());
//get the MoParts of the line.
CMoParts myParts(myLine.GetParts());
//get the vertice points.
CMoPoints myPoints(myParts.Item(COleVariant((short)0)));
//get the number of vertices.
long num = myPoints.GetCount();
if (num > 1)
{
//get the first point.
CMoPoint ptFirst( myPoints.Item(COleVariant((short)0)));
//get the last point of the line.
CMoPoint ptLast(myPoints.Item(COleVariant((short)num-1)));
}
/*** END CODE **/
--------------------------------------------------------------------------------
6.对所有图层依次执行某个操作的示例代码:
使用循环可以遍历各个图层,但是你必须匹配图层的title后放可知道该图层是你所需要的图层
此代码还演示了如何使用技巧获得所有图层的最适合的Extent。
--------------------------------------------------------------------------------
double dLimit_Bottom,dLimit_top,dLimit_left,dLimit_right;
dLimit_Bottom = dLimit_top = dLimit_left = dLimit_right =0;
CMoLayers layers(m_map.GetLayers());
for(short i=0; i < layers.GetCount(); i++) //对所有图层
{
CMoMapLayer layer(layers.Item(COleVariant(i) ));
if (! layer.GetLayerType()==moMapLayer ){
MessageBox( _T("图层必须是Shape图层,你设置的不是。对不起,无法载入。"), _T("提示"), MB_OK|MB_ICONWARNING);
return ;
}
//设置Extent
CMoRectangle RectExtent (layer.GetExtent());
if (RectExtent.GetBottom() < dLimit_Bottom) dLimit_Bottom =RectExtent.GetBottom();
if (RectExtent.GetTop() > dLimit_top) dLimit_top =RectExtent.GetTop();
if (RectExtent.GetLeft() < dLimit_left) dLimit_left =RectExtent.GetLeft();
if (RectExtent.GetRight() > dLimit_right) dLimit_right =RectExtent.GetRight();
//如果是指定的图层,则
if ( "YourShapeTitle" == layer.GetName()){
//do something like follow code:
if (moShapeTypeLine!= layer.GetShapeType()){
MessageBox( _T("图层必须是线图层"), _T("提示"), MB_OK|MB_ICONWARNING);
return ;
}//end if (moShapeTypeLine!= layer.GetShapeType())
}// end if ( "YourShapeTitle" == layer.GetName())
}// end for(short i=0; i < layers.GetCount(); i++)
extent.SetBottom (dLimit_Bottom );
extent.SetTop(dLimit_top);
extent.SetLeft(dLimit_left);
extent.SetRight(dLimit_right);
extent.ScaleRectangle(1.2);
m_map.SetFullExtent (extent);
m_map.SetExtent(extent);
--------------------------------------------------------------------------------
7.利用CMoValueMapRenderer为同一图层N个多边形着色:
演示代码如下: (代码9中转载了另外一种方法,可以指定颜色而不是随机颜色。请见9改变图层颜色)
--------------------------------------------------------------------------------
short i = 0;
CMoMapLayer layer(layers.Item(COleVariant(i) ));
//将每个polygon取出,并为每个多边形着色。
CMoRecordset recs(layer.GetRecords()); // used to hold all polygons
CMoStrings strings;
VERIFY(strings.CreateDispatch(TEXT("MapObjects2.Strings")));
CMoFields fields(recs.GetFields());
while (!recs.GetEof())
{
CMoField Density(fields.Item(COleVariant("Density"))); //这里Density 是一个属性,你可以替代成你自己定义的属性
strings.Add(Density.GetValueAsString());
recs.MoveNext();
} //end while (!recs.GetEof())
//如果多于1个polygon,则为每个多边形着色
if( recs.GetCount() > 1){
//
// Set up value map renderer
//
CMoValueMapRenderer vmRenderer;
VERIFY(vmRenderer.CreateDispatch(TEXT("MapObjects2.ValueMapRenderer")));
vmRenderer.SetField(TEXT("Density"));
vmRenderer.SetValueCount(strings.GetCount());
for (short i = 0; i < strings.GetCount(); i++)
vmRenderer.SetValue(i, strings.Item(COleVariant(i)));
layer.SetRenderer(vmRenderer);
//着色完毕
} //end if( recs.GetCount() > 1)
--------------------------------------------------------------------------------
8.制作一个点图层(转载):
(来自CSDN)有些时候将一些固定的数据制作成图层,可以提高程序的速度,而且使用方便。下面我就将对图层的制作方法进行一下简单的说明。
假设我们要将一些经纬度坐标用点的方式画在地图上,那么我们首先要有保存经纬度坐标的数组:m_LonArray, m_LatArray,均为CArray<float,float>型。然后我们在CMyView中增加一些成员变量:
CmoDataConnectionpMoCon;
CMoTableDescdesc;
CMoMapLayerlayer;
CMoPointm_point;
好了,是为创建新图层增加一个函数的时候了,在视图类中增加函数:CreateNewLayer()。
演示代码如下:
--------------------------------------------------------------------------------
BOOL CMyView:: CreateNewLayer ()
{
if (!pMoCon.CreateDispatch(TEXT("MapObjects2.DataConnection")))
return FALSE;
if(!desc.CreateDispatch("MapObjects2.TableDesc"))
return FALSE;
VARIANT vt;
vt.vt = VT_BOOL;
vt.boolVal = VARIANT_FALSE;
pMoCon.SetDatabase((LPCTSTR)"E:\\Demo\\经纬度层"); //设置图层保存目录
if(!pMoCon.Connect())
return FALSE;
//设置图层的字段个数及属性,这里设置两个,一个为Number,一个为Name。表示点的号码及名称。
desc.SetFieldCount(2);
desc.SetFieldType(0,moString);
desc.SetFieldName(0,"Number");
desc.SetFieldLength(0,10);
desc.SetFieldType(1,moString);
desc.SetFieldName(1, "Name");
desc.SetFieldLength(1, 10);
//创建新图层,设置名称、类型及字段。
CmoGeoDataSet geoDataset(pMoCon.AddGeoDataset(“经纬度层”, moShapeTypePoint,
(LPDISPATCH)desc, vt, vt);
if (!layer.CreateDispatch(TEXT("MapObjects2.MapLayer")))
return FALSE;
//设置图层的记录集
layer.SetGeoDataset(geoDataset);
CMoRecordset recs(layer.GetRecords());
CMoFields fields(recs.GetFields());
for(int i=0; i< m_LonArray.GetSize(); i++)
{
recs.AddNew();
m_point.SetX(m_ LonArray.GetAt(i));
m_point.SetY(m_ LatArray.GetAt(i));
SetValue(fields, "Shape",m_point);
SetValue(fields, "Number",m_Number.GetAt(i));//需定义CStringArray m_Number
SetValue(fields, "Name", m_Chname.GetAt(i));//需定义CStrignArray m_Name
recs.Update();
}
//设置点的颜色,并加入地图。
layer.GetSymbol().SetColor(moLightYellow);
CMoLayers layers(m_map.GetLayers());
layers.Add(layer);
return TRUE;
}
--------------------------------------------------------------------------------
好了,调用一下试试效果吧。
9.改变图层颜色(转载)
另外一个简单的随机颜色填充在示例7,请参考7。原作者:张松伟 zswking@163.com
如果你的地国正在显示一个“中国地图”的图层,而图层中每个省的颜色都是一样的,你是不是想把它做成真实地图一样的效果,给各个省填上颜色呢?好,让我们开始吧。
注意,一定要确保你的“中图地图”图层数据中有标识各个省的数据和字段(可以在ArcMap中看到),因为只有能区别出各个区域才能对区域填色,现在我们假设图层名称为China, 标识各个省的字段为NAME。好了,在你程序中加入改变颜色的函数吧。
演示代码如下:
--------------------------------------------------------------------------------
void CMapCortrol::ChangeChinaColor()
{
CMoRecordset recs; //图层的记录集
CMoStrings strs; //MO的字符串类
strs.CreateDispatch("MapObjects2.Strings");
//得到图层数据中NAME字段的第条记录,保存在strs中。
CMoMapLayer lay = m_map.GetLayers().Item(COleVariant("China"));
recs = lay.GetRecords();
while(!recs.GetEof())
{
CMoFields mfs = recs.GetFields();
CMoField mf = mfs.Item(COleVariant("NAME"));
CString s = mf.Get_Value().bstrVal;
strs.Add(s);
recs.MoveNext();
}
//改变区域颜色
CMoValueMapRenderer vmRend;
vmRend.CreateDispatch("MapObjects2.ValueMapRenderer");
vmRend.SetValueCount(strs.GetCount());
vmRend.SetField("NAME");
for(int i=0; i< strs.GetCount(); i++)
{
//将保存的省名附给vmRend
VARIANT V;
V.vt = VT_I2;
V.iVal = i;
vmRend.SetValue(i, strs.Item(V));
//取出省名并进行判断
if(vmRend.GetValue(i) == "北京市" || vmRend.GetValue(i) == "上海市" ||
vmRend.GetValue(i) == "江西省" || vmRend.GetValue(i) == "四川省")
{
vmRend.GetSymbol(i).SetColor(RGB(239,252,230));
}
else if(vmRend.GetValue(i) == "安徽省" || vmRend.GetValue(i) == "黑龙江" ||
vmRend.GetValue(i) == "辽宁省" || vmRend.GetValue(i) == "广西壮族自治区" ||
vmRend.GetValue(i) == "台湾省" || vmRend.GetValue(i) == "甘肃省" ||
vmRend.GetValue(i) == "天津市" || vmRend.GetValue(i) == "山西省")
{
vmRend.GetSymbol(i).SetColor(RGB(241,232,252));
}
else if(vmRend.GetValue(i) == "山东省" || vmRend.GetValue(i) == "陕西省" ||
vmRend.GetValue(i) == "湖南省" || vmRend.GetValue(i) == "海南省" ||
vmRend.GetValue(i) == "澳门" || vmRend.GetValue(i) == "香港")
{
vmRend.GetSymbol(i).SetColor(RGB(252,237,248));
}
else if(vmRend.GetValue(i) == "河南省" || vmRend.GetValue(i) == "内蒙古自治区" ||
vmRend.GetValue(i) == "福建省" || vmRend.GetValue(i) == "贵州省" ||
vmRend.GetValue(i) == "青海省")
{
vmRend.GetSymbol(i).SetColor(RGB(252,251,235));
}
else if(vmRend.GetValue(i) == "江苏省" || vmRend.GetValue(i) == "西藏自治区")
{
vmRend.GetSymbol(i).SetColor(RGB(252,230,246));
}
else if(vmRend.GetValue(i) == "吉林省" || vmRend.GetValue(i) == "河北省" ||
vmRend.GetValue(i) == "浙江省" || vmRend.GetValue(i) == "湖北省" ||
vmRend.GetValue(i) == "广东省" || vmRend.GetValue(i) == "新疆维吾尔族自治区" || vmRend.GetValue(i) == "云南省" || vmRend.GetValue(i) == "宁夏回族自治区")
{
vmRend.GetSymbol(i).SetColor(RGB(245,252,252));
}
//设置省界的颜色
vmRend.GetSymbol(i).SetOutlineColor(RGB(185,185,185));
}
lay.SetRenderer(vmRend);
m_map.Refresh();
}
--------------------------------------------------------------------------------
10.Fields不能通过索引号来获取Field,怎么办?
mo中Fields不能通过索引号来获取Field,只提供了通过字段名称来获取字段的方法,代码如下
--------------------------------------------------------------------------------
short i = 0;
CMoMapLayer layer(layers.Item(COleVariant(i) ));
CMoRecordset recs(layer.GetRecords()); // used to hold all shapes
CMoFields Fields(recs.GetFields());
while (!recs.GetEof())
{
CMoFieldShapeField(Fields.Item(COleVariant(TEXT("Shape")))); //指定字段名
//加入你的代码
recs.MoveNext();
} //end while (!recs.GetEof())
--------------------------------------------------------------------------------
有两种方法可以解决此问题: 一是通过TableDesc来获取Recordset的结构,但是只能获取到属性字段,空间字段无法获取(应该是Shape/FeatureID两个字段获取不到,其他都可以), 详见CMoTableDesc类的GetFieldName()方法。代码如下
--------------------------------------------------------------------------------
CMoDataConnection conn, CMoTableDesc tableDesc
CMoGeoDataset geoDataset(conn.AddGeoDataset(GetFileTitle(m_path), moLine, tableDesc, va ,va));
ASSERT(LPDISPATCH(geoDataset));
CString strFieldName;
for (i=0;i< tableDesc.GetFieldCount; i++)
strFieldName = tableDesc.GetFieldName;
--------------------------------------------------------------------------------
另外也可以用CMoIterator这个类。一般的,对于collection的对象都可以用CMoIterator这个类。示例代码如下:
--------------------------------------------------------------------------------
short j = 0;
CMoMapLayer layer(layers.Item(COleVariant(j) ));
CMoRecordset recs(layer.GetRecords()); // used to hold all shapes
CMoFields fields(recs.GetFields());
int iCount=fields.GetCount();
CMoIterator moIterator(fields);
CMoField field;
moIterator.Reset();
for(int i=0;i< iCount;i++)
{
moIterator.Next(field);
TRACE("name=%s\n",field.GetName());
}
--------------------------------------------------------------------------------
11.判断图层类型是点、线还是面图层。
对一个layer对象使用GetShapeType而不是GetLayerType函数。GetLayerType函数用于判断一个图层是矢量还是栅格的。演示代码如下:
--------------------------------------------------------------------------------
CMoLayers layers(m_map.GetLayers());
if (! layer.GetLayerType()==moMapLayer ){ //常量moMapLayer表示矢量图,moImageLayer表示Image图
MessageBox( _T("图层必须是Shape图层,你设置的不是。对不起,无法载入。"), _T("提示"), MB_OK|MB_ICONWARNING);
return FALSE;
}
for(short i=0;i< layers.GetCount();i++) //对所有图层
{
CMoMapLayer layer(layers.Item(COleVariant(i) ));
if (moShapeTypeLine != layer.GetShapeType())//如果不是线,常量moShapeTypeLine等定义见MapObject2.h
{
//add your code here!
}//end if (moShapeTypeLine != layer.GetShapeType())
}//end for(short i=0;i< layers.GetCount();i++)
--------------------------------------------------------------------------------
12.在指定的目录下保存全部图层文件。
在szPath指定的目录下保存全部图层。演示代码如下:
--------------------------------------------------------------------------------
void CMoCov2ShpView::SaveAsShp(CString szPath)
{
CMoRecordset rst;
CMoGeoDataset dst;
CMoMapLayer ly;
try
{
rst.CreateDispatch(_T("MapObject2.Recordset"));
ly.CreateDispatch(_T("MapObject2.MapLayer"));
}
catch(COleException *ep)
{
ep->ReportError();
return;
}
CString szFileName;
CMoLayers lys(m_objMap.GetLayers());
int ilyCounts;
ilyCounts = lys.GetCount();
for(int i = 0;i < ilyCounts;i ++)
{
try
{
ly = lys.Item(COleVariant((short)i));
szFileName = ly.GetName();
if(szFileName.IsEmpty() != NULL)
{
szFileName.Format("AutoFileName%d",i);
}
szFileName = szPath + "\\" + szFileName + ".shp";
rst = ly.GetRecords();
rst.Export(szFileName,ly.GetCoordinateSystem());
}
catch(COleException *ep)
{
ep->ReportError();
}
}//end for(int i = 0;i < ilyCounts;i ++)
}
--------------------------------------------------------------------------------
13.如何合并两个图层?
下面是图层合并的演示代码:
--------------------------------------------------------------------------------
void CMoAddShapeView::MergeLayers()
{
CMoTableDesc oTDesc;
CMoGeoDataset oDataset;
CMoDataConnection oConnection;
CMoRecordset oRecset;
CMoMapLayer oLayer,oTempLayer;
CMoRecordset oTempRecs;
CMoField oField;
CMoFields oFields;
CMoFields oTempFields;
CString szMergeFile;
long lshpType;
CString szPath;
char chPath[MAX_PATH];
int ilen = 0;
int fCounts;
CString szFName;
CMoLayers oLayers(m_objMap.GetLayers());
if( oLayers.GetCount() < 2) //小于2个图层无法合并
return;
oTempLayer = oLayers.Item(COleVariant((short)(oLayers.GetCount() -1)));
oRecset = oTempLayer.GetRecords();
lshpType = oTempLayer.GetShapeType();
if(m_strMergeFile.IsEmpty() != NULL)
{
szMergeFile = oTempLayer.GetName();
}
else
{
szMergeFile = m_strMergeFile;
}
if(!oConnection.CreateDispatch(TEXT("MapObjects2.DataConnection")))
return;
if(!oLayer.CreateDispatch(TEXT("MapObjects2.MapLayer")))
return;
GetCurrentDirectory(MAX_PATH,chPath);
ilen = strlen(chPath);
chPath[ilen] = '\0';
szPath = chPath;//[ilen];
oConnection.SetDatabase(szPath);
if(oConnection.Connect())
{
VARIANT va;
VariantInit(&va);
va.vt =VT_BOOL;
va.bVal = false;
oTDesc = oRecset.GetTableDesc();
//oDataset = oConnection.AddGeoDataset("Merged",lshpType,oTDesc,va,va);
if(szMergeFile.IsEmpty() != NULL)
{
CTime tm(CTime::GetCurrentTime());
szMergeFile = "Merged" + tm.Format("%H%M%S");
}
oDataset = oConnection.AddGeoDataset(szMergeFile,lshpType,oTDesc,va,va);
if(oDataset == NULL)
return;
oLayer.SetGeoDataset(oDataset);
oTempRecs = oLayer.GetRecords();
oTempRecs.SetAutoFlush(FALSE);
for(int i= oLayers.GetCount() -1;i >= 0;i --)
{
oTempLayer = oLayers.Item(COleVariant((short)i));
oRecset = oTempLayer.GetRecords();
if(lshpType != oTempLayer.GetShapeType())
continue;
if(!TableDescMatch(oTDesc,oRecset.GetTableDesc()))
continue;
oRecset.MoveFirst();
while(!oRecset.GetEof())
{
oTempRecs.AddNew();
fCounts = oTDesc.GetFieldCount();
VARIANT v;
for(short j = 0;j < fCounts;j++)
{
szFName = oTDesc.GetFieldName(j);
OutputDebugString(szFName + "\n\r");
if(szFName.CompareNoCase("Shape") == NULL)
{
VariantInit(&v);
v = oRecset.GetFields().Item(COleVariant(TEXT(szFName))).Getvalue();
LPDISPATCH value;
v.vt = VT_DISPATCH;
value = v.pdispVal;
Setvalue(oTempRecs.GetFields(),szFName,value);
}
else
{
oTempRecs.GetFields().Item(COleVariant(TEXT(szFName))).Setvalue(oRecset.GetFields().Item(COleVariant(TEXT(szFName))).Getvalue());
}//end if(szFName.CompareNoCase("Shape") == NULL)
}//end for(short j = 0;j < fCounts;j++)
VariantInit(&v);
v = oRecset.GetFields().Item(COleVariant(TEXT("shape"))).Getvalue();
LPDISPATCH value;
v.vt = VT_DISPATCH;
value = v.pdispVal;
Setvalue(oTempRecs.GetFields(),"Shape",value);
Setvalue(oTempRecs.GetFields(),"FeatureID",oRecset.GetFields().Item(COleVariant(TEXT("FeatureID"))).Getvalue());
oTempRecs.Update();
oRecset.MoveNext();
}//while(!oRecset.GetEof())
} //end for(int i= oLayers.GetCount() -1;i >= 0;i --)
oTempRecs.SetAutoFlush(TRUE);
}// end if(oConnection.Connect())
oLayers.Clear();
oLayers.Add(oLayer);
m_objMap.Refresh();
}