GIS二次开发学习专题(二) 基本地图控件使用
学习资料来自《牟乃夏 AE开发教程—基于C#.NET》
发的代码是我整理+老师布置的作业
这一部分是地图基本控件的使用与编写,包括:
一、二维控件的使用
二、自行编写代码:添加数据、控制地图:打开文件、添加数据、漫游、全图、放大、缩小、刷新、保存、另存为
三、TOCControl的右键菜单
四、鹰眼视图
一、二维控件的使用
拖入“ToolBarControl”,“TOCControl”,“MapControl”,“LicenseControl”控件,在“ToolBarControl”中添加按钮、设置“LicenseControl”
二、自行编写代码:添加数据、控制地图
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ESRI.ArcGIS.SystemUI;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.DataSourcesFile;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.DataSourcesRaster;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Display;
string m_BasicOperationTool = ""; //定义一个操作按钮变量
public Form1()
{
ESRI.ArcGIS.RuntimeManager.Bind(ESRI.ArcGIS.ProductCode.Engine);
InitializeComponent();
}
1.ToolBarControl:
打开文件:
采用OpenFileDialog进行操作:
/*打开文件按钮*/
private void tlbOpen_Click(object sender, EventArgs e)
{
System.Windows.Forms.OpenFileDialog openFileDialog;
openFileDialog = new OpenFileDialog();
openFileDialog.Title = "open map document";
openFileDialog.Filter = "map document(*.mxd)|*.mxd"; //文件过滤器
openFileDialog.ShowDialog();
string strFilePath = openFileDialog.FileName; //选择文件路径
if (axMapControl1.CheckMxFile(strFilePath))
{
//加载mxd文档之前的鼠标指针,esriPointerArrowHourglass为等待光标
axMapControl1.MousePointer = ESRI.ArcGIS.Controls.esriControlsMousePointer.esriPointerArrowHourglass;
//LoadMxFile方法有三个参数,文件路径、地图名称或索引和密码,也可以直接重载为只有一个文件路径参数
axMapControl1.LoadMxFile(strFilePath, 0, Type.Missing);//axMapControl1.LoadMxFile(strFilePath);
//加载mxd文档后的鼠标指针,esriPointerDefault为默认箭头
axMapControl1.MousePointer = ESRI.ArcGIS.Controls.esriControlsMousePointer.esriPointerDefault;
}
else
{
//不能加载mxd或加载失败时出现消息对话框
MessageBox.Show(strFilePath + " is not a valid map document");
}
}
全图、放大、缩小、漫游、刷新:
都是采用点击之后用一个记录操作的字符串去记录,然后用一个方法根据操作去执行。此处是给每一个操作赋予名字,且改变光标样式。
/*全图浏览按钮*/
private void tlbGlobal_Click(object sender, EventArgs e)
{
m_BasicOperationTool = "isZoomFull";
axMapControl1.Extent = axMapControl1.FullExtent; //变为全图显示,按钮直接生效
axMapControl1.MousePointer = esriControlsMousePointer.esriPointerZoom;//设置鼠标指针样式
}
/*放大按钮*/
private void tlbZoomIn_Click(object sender, EventArgs e)
{
m_BasicOperationTool = "ZoomIn";
axMapControl1.MousePointer = esriControlsMousePointer.esriPointerZoomIn;
}
/*缩小按钮*/
private void tlbZoomOut_Click(object sender, EventArgs e)
{
m_BasicOperationTool = "ZoomOut";
axMapControl1.MousePointer = esriControlsMousePointer.esriPointerZoomOut;
}
/*刷新*/
private void tlbRefresh_Click(object sender, EventArgs e)
{
m_BasicOperationTool = "Refresh";
axMapControl1.Refresh(); //点击直接生效
axMapControl1.MousePointer = esriControlsMousePointer.esriPointerZoom; //```
}
/*漫游*/
private void tlbPan_Click(object sender, EventArgs e)
{
m_BasicOperationTool = "ZoomPan";
axMapControl1.MousePointer = esriControlsMousePointer.esriPointerPan;
}
点击地图的操作,需要设置axMapControl1的onMouseDown属性
/*点击地图界面的操作*/
private void axMapControl1_OnMouseDown(object sender, IMapControlEvents2_OnMouseDownEvent e)
{
//在axMapControl1上进行点击后才生效的功能,如放大缩小和漫游
IEnvelope objEnvelope = null; //地物包路线,地物最小外接矩形
IPoint pPoint = null;
IActiveView pActiveView = axMapControl1.ActiveView.FocusMap as IActiveView;
pPoint = pActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(e.x, e.y); //获取mousedown点
switch (m_BasicOperationTool)
{
case "ZoomIn":
objEnvelope = axMapControl1.TrackRectangle(); //TrackRectangle为拉框矩形橡皮筋
axMapControl1.Extent = objEnvelope;
break;
case "ZoomOut":
objEnvelope = axMapControl1.TrackRectangle();
double mapWidth = objEnvelope.Width;
double mapHeight = objEnvelope.Height;
double x1 = pPoint.X;
double x2 = pPoint.X + mapWidth;
double y1 = pPoint.Y;
double y2 = pPoint.Y - mapHeight * 2;
objEnvelope.XMax = x2 + mapWidth * 2;
objEnvelope.XMin = x1 - mapWidth * 2;
objEnvelope.YMax = y2 - mapHeight * 2;
objEnvelope.YMin = y1 + mapHeight * 2;
axMapControl1.Extent = objEnvelope;
break;
case "ZoomPan":
axMapControl1.Pan();
break;
}
}
添加数据:
添加矢量数据与栅格数据:
private void tlbAddDate_Click(object sender, EventArgs e)
{
OpenFileDialog pOpenFileDialog = new OpenFileDialog();
pOpenFileDialog.CheckFileExists = true;
pOpenFileDialog.Title = "选择需要加载的地理数据文件";
pOpenFileDialog.Filter = "Shape格式文件(*.shp)|*.shp|栅格文件(*.bmp;*.tif;*.jpg;*.img)|*.bmp;*.tif;*.jpg;*.img|(*.bmp)|*.bmp|(*.tif)|*.tif|(*.jpg)|*.jpg|(*.img)|*.img";
pOpenFileDialog.ShowDialog();
string pRasterFileName = pOpenFileDialog.FileName;
if (pRasterFileName == "")
return;
string strFNaExten = System.IO.Path.GetExtension(pRasterFileName); //获得文件扩展名
string pPath = System.IO.Path.GetDirectoryName(pRasterFileName); //返回指定路径字符串的目录信息
string pFileName = System.IO.Path.GetFileName(pRasterFileName); //返回指定路径字符串的文件名和扩展名
if (strFNaExten == ".shp")
{
string oFileName = System.IO.Path.GetFileNameWithoutExtension(pRasterFileName); //返回不具有扩展名的指定路径字符串的文件名
axMapControl1.AddShapeFile(pPath, oFileName); //加载地图
}
else
{
IWorkspaceFactory pWorkspaceFactory = new RasterWorkspaceFactory();//创建工作空间工厂对象
IWorkspace pWorkspace = pWorkspaceFactory.OpenFromFile(pPath, 0); //打开
IRasterWorkspace pRasterWorkspace = pWorkspace as IRasterWorkspace; //接口的实现
IRasterDataset pRasterDataset = pRasterWorkspace.OpenRasterDataset(pFileName);
//影响金字塔判断与创建
IRasterPyramid3 pRasPyrmid;
pRasPyrmid = pRasterDataset as IRasterPyramid3;
if (pRasPyrmid != null)
{
if (!(pRasPyrmid.Present))
{
pRasPyrmid.Create();//创建金字塔
}
}
IRaster pRaster;
pRaster = pRasterDataset.CreateDefaultRaster();
IRasterLayer pRasterLayer;
pRasterLayer = new RasterLayerClass();
pRasterLayer.CreateFromRaster(pRaster);
ILayer pLayer = pRasterLayer as ILayer;
axMapControl1.AddLayer(pLayer, 0);
}
}
保存:
private void tlbSaveMap_Click(object sender, EventArgs e)
{
try
{
string filePath = axMapControl1.DocumentFilename;
IMapDocument pMapDocument = new MapDocumentClass();
if (filePath != null && axMapControl1.CheckMxFile(filePath))
{
if (pMapDocument.get_IsReadOnly(filePath))
{
MessageBox.Show("本地图文档为只读,不能保存!");
pMapDocument.Close();
return;
}
}
else
{
SaveFileDialog pSaveFileD = new SaveFileDialog();
pSaveFileD.Title = "请选择保存路径";
pSaveFileD.OverwritePrompt = true; //
pSaveFileD.Filter = "ArcMap文档(*.mxd)|X.mxd|ArcMap模板(*.mxt)|*.mxt";
pSaveFileD.RestoreDirectory = true; //
if (pSaveFileD.ShowDialog() == DialogResult.OK) //
{
filePath = pSaveFileD.FileName;
}
else
{
return;
}
}
pMapDocument.New(filePath);
pMapDocument.ReplaceContents(axMapControl1.Map as IMxdContents); //
pMapDocument.Save(pMapDocument.UsesRelativePaths, true);
pMapDocument.Close();
MessageBox.Show("保存地图文档成功!");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
另存为:
private void tlbSaveAs_Click(object sender, EventArgs e)
{
try
{
SaveFileDialog pSaveFileD = new SaveFileDialog();
pSaveFileD.Title = "另存为";
pSaveFileD.OverwritePrompt = true; //
pSaveFileD.Filter = "ArcMap文档(*.mxd)|X.mxd|ArcMap模板(*.mxt)|*.mxt";
pSaveFileD.RestoreDirectory = true; //
if (pSaveFileD.ShowDialog() == DialogResult.OK) //
{
string filePath = pSaveFileD.FileName;
IMapDocument pMapDocument = new MapDocumentClass(); //
pMapDocument.New(filePath);
pMapDocument.ReplaceContents(axMapControl1.Map as IMxdContents);
pMapDocument.Save(true, true); //
pMapDocument.Close();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
三、TocControl右键菜单
支持的功能:
需要新建一个form,拖入GirdView窗格,用于显示属性表
设置axTOCControl1的OnMouseDown属性:
IFeatureLayer pTocFeatureLayer = null;
private FormAtrribute frmAttribute = null;
private ILayer pMoveLayer = null;
private int toIndex;
private void axTOCControl1_OnMouseDown(object sender, ESRI.ArcGIS.Controls.ITOCControlEvents_OnMouseDownEvent e)
{
if (e.button == 2) //单击右键,左键为1
{
esriTOCControlItem item = esriTOCControlItem.esriTOCControlItemNone;
IBasicMap map = null; //对属性值初始化,也可以=null;
ILayer pLayer = null;
object other = null;
object index = null;
axTOCControl1.HitTest(e.x, e.y, ref item, ref map, ref pLayer, ref other, ref index); //实现赋值,ref的参数必须初始化
pTocFeatureLayer = pLayer as IFeatureLayer;
if (item == esriTOCControlItem.esriTOCControlItemLayer && pTocFeatureLayer != null) //点击的是图层的话,就显示右键菜单
{
tsm_Selectable.Enabled = !pTocFeatureLayer.Selectable;
tsm_unSelectable.Enabled = pTocFeatureLayer.Selectable;
ContextMenuStrip1.Show(Control.MousePosition);
}
}
}
/*属性表*/
private void tsm_property_Click(object sender, EventArgs e)
{
if (frmAttribute == null || frmAttribute.IsDisposed)
{
frmAttribute = new FormAtrribute();
}
frmAttribute.CurFeatureLayer = pTocFeatureLayer;
frmAttribute.InitUI();
frmAttribute.ShowDialog();
}
/*移除图层*/
private void tsm_Remove_Click(object sender, EventArgs e)
{
if (pTocFeatureLayer == null) return;
DialogResult result = MessageBox.Show("是否删除[" + pTocFeatureLayer.Name + "]图层", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Information);
if (result == DialogResult.OK)
{
axMapControl1.Map.DeleteLayer(pTocFeatureLayer);
}
axMapControl1.ActiveView.Refresh();
}
/*缩放到图层*/
private void tsm_ScaleToLayer_Click(object sender, EventArgs e)
{
if (pTocFeatureLayer == null) return;
(axMapControl1.Map as IActiveView).Extent = pTocFeatureLayer.AreaOfInterest;
(axMapControl1.Map as IActiveView).PartialRefresh(esriViewDrawPhase.esriViewGeography, null, null);
}
/*图层可选*/
private void tsm_Selectable_Click(object sender, EventArgs e)
{
pTocFeatureLayer.Selectable = true;
tsm_Selectable.Enabled = !tsm_Selectable.Enabled;
}
/*图层不可选*/
private void tsm_unSelectable_Click(object sender, EventArgs e)
{
pTocFeatureLayer.Selectable = false;
tsm_Selectable.Enabled = !tsm_Selectable.Enabled;
}
四、鹰眼视图
/// <summary>
/// 鹰眼
/// </summary>
private bool bCanDrag; //鹰眼地图上矩形框可移动的标志
private IPoint pMoveRectPoint; //记录在移动鹰眼地图上的矩形框时鼠标的位置
private IEnvelope pEnv; //记录数据视图的Event
/*确保鹰眼视图与数据视图的一致*/
private void axMapControl1_OnMapReplaced(object sender, IMapControlEvents2_OnMapReplacedEvent e)
{
if (EagleEyeMapControl2.LayerCount > 0)
{
EagleEyeMapControl2.ClearLayers();
}
//设置鹰眼和主地图的坐标系一致
EagleEyeMapControl2.SpatialReference = axMapControl1.SpatialReference;
for (int i = axMapControl1.LayerCount - 1; i >= 0;i-- )
{
//使鹰眼地图与数据视图的图层上下顺序保持一致
ILayer pLayer = axMapControl1.get_Layer(i);
if (pLayer is IGroupLayer || pLayer is ICompositeLayer)
{
ICompositeLayer pCompositeLayer = (ICompositeLayer)pLayer;
for (int j = pCompositeLayer.Count - 1; j >= 0; j--)
{
ILayer pSubLayer = pCompositeLayer.get_Layer(j);
IFeatureLayer pFeatureLayer = pSubLayer as IFeatureLayer;
if (pFeatureLayer != null)
{
if (pFeatureLayer.FeatureClass.ShapeType != esriGeometryType.esriGeometryPoint && pFeatureLayer.FeatureClass.ShapeType != esriGeometryType.esriGeometryMultipoint)
{
EagleEyeMapControl2.AddLayer(pLayer);
}
}
}
}
else
{
IFeatureLayer pFeatureLayer = pLayer as IFeatureLayer;
if (pFeatureLayer != null)
{
if (pFeatureLayer.FeatureClass.ShapeType != esriGeometryType.esriGeometryPoint && pFeatureLayer.FeatureClass.ShapeType != esriGeometryType.esriGeometryMultipoint)
{
EagleEyeMapControl2.AddLayer(pLayer);
}
}
//设置鹰眼地图全图显示
EagleEyeMapControl2.Extent = axMapControl1.FullExtent;
pEnv = axMapControl1.Extent as IEnvelope;
DrawRectangle(pEnv);
EagleEyeMapControl2.ActiveView.Refresh();
}
}
copyToPageLayout(); //数据视图与布局视图的数据拷贝
}
/*鹰眼与数据视图同步*/
private void SynchronizeEagleEye()
{
if (EagleEyeMapControl2.LayerCount > 0)
{
EagleEyeMapControl2.ClearLayers();
}
//设置鹰眼和主地图的坐标系一致
EagleEyeMapControl2.SpatialReference = axMapControl1.SpatialReference;
for (int i = axMapControl1.LayerCount - 1; i >= 0; i--)
{
//使鹰眼地图与数据视图的图层上下顺序保持一致
ILayer pLayer = axMapControl1.get_Layer(i);
if (pLayer is IGroupLayer || pLayer is ICompositeLayer)
{
ICompositeLayer pCompositeLayer = (ICompositeLayer)pLayer;
for (int j = pCompositeLayer.Count - 1; j >= 0; j--)
{
ILayer pSubLayer = pCompositeLayer.get_Layer(j);
IFeatureLayer pFeatureLayer = pSubLayer as IFeatureLayer;
if (pFeatureLayer != null)
{
if (pFeatureLayer.FeatureClass.ShapeType != esriGeometryType.esriGeometryPoint && pFeatureLayer.FeatureClass.ShapeType != esriGeometryType.esriGeometryMultipoint)
{
EagleEyeMapControl2.AddLayer(pLayer);
}
}
}
}
else
{
IFeatureLayer pFeatureLayer = pLayer as IFeatureLayer;
if (pFeatureLayer != null)
{
if (pFeatureLayer.FeatureClass.ShapeType != esriGeometryType.esriGeometryPoint && pFeatureLayer.FeatureClass.ShapeType != esriGeometryType.esriGeometryMultipoint)
{
EagleEyeMapControl2.AddLayer(pLayer);
}
}
//设置鹰眼地图全图显示
EagleEyeMapControl2.Extent = axMapControl1.FullExtent;
pEnv = axMapControl1.Extent as IEnvelope;
DrawRectangle(pEnv);
EagleEyeMapControl2.ActiveView.Refresh();
}
}
}
/*画矩形框*/
private void DrawRectangle(IEnvelope pEnvelope)
{
//绘制前,清除之前的矩形框
IGraphicsContainer pGraphicsContainer = EagleEyeMapControl2.Map as IGraphicsContainer;
IActiveView pActiveView = pGraphicsContainer as IActiveView;
pGraphicsContainer.DeleteAllElements();
//当前视图范围
IRectangleElement pRectangleElement = new RectangleElementClass();
IElement pElement = pRectangleElement as IElement;
pElement.Geometry = pEnvelope;
//设置矩形框
IRgbColor pColor = new RgbColor();
pColor = GetRgbColor(255,0,0); //红
pColor.Transparency = 255;
ILineSymbol pOutLine = new SimpleLineSymbol();
pOutLine.Width = 2;
pOutLine.Color = pColor;
IFillSymbol pFillSymbol = new SimpleFillSymbol();
pColor = new RgbColor(); //
pColor.Transparency = 0;
pFillSymbol.Color = pColor;
pFillSymbol.Outline = pOutLine;
//添加矩形框
IFillShapeElement pFillShapeElement = pElement as IFillShapeElement;
pFillShapeElement.Symbol = pFillSymbol;
pGraphicsContainer.AddElement((IElement)pFillShapeElement, 0);
//刷新
pActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics,null,null);
}
/*添加矩形框与数据视图范围的联动*/
private void EagleEyeMapControl2_OnExtentUpdated(object sender, IMapControlEvents2_OnExtentUpdatedEvent e)
{
IEnvelope pEnvelope = (IEnvelope)e.newEnvelope;
DrawRectangle(pEnvelope);
}
/*点击鹰眼视图绘制矩形框*/
private void EagleEyeMapControl2_OnMouseDown(object sender, IMapControlEvents2_OnMouseDownEvent e)
{
if (EagleEyeMapControl2.Map.LayerCount > 0)
{
if (e.button == 1) //左键
{
if (e.mapX > pEnv.XMin && e.mapY > pEnv.YMin)
{
bCanDrag = true;
}
pMoveRectPoint = new ESRI.ArcGIS.Geometry.Point(); //
pMoveRectPoint.PutCoords(e.mapX,e.mapY);
}
else if (e.button == 2) //鼠标右键
{
IEnvelope pEnvelope = EagleEyeMapControl2.TrackRectangle();
IPoint pTempPoint = new ESRI.ArcGIS.Geometry.Point(); //
pTempPoint.PutCoords(pEnvelope.XMin + pEnvelope.Width / 2, pEnvelope.YMin + pEnvelope.Height / 2);
axMapControl1.Extent=pEnvelope;
//矩形框的高宽进行中心调整
axMapControl1.CenterAt(pTempPoint);
}
}
}
/*拖动矩形框*/
private void EagleEyeMapControl2_OnMouseMove(object sender, IMapControlEvents2_OnMouseMoveEvent e)
{
if (e.mapX > pEnv.XMin && e.mapY > pEnv.YMin && e.mapX < pEnv.XMax && e.mapY < pEnv.YMax)
{
//
EagleEyeMapControl2.MousePointer = esriControlsMousePointer.esriPointerHand;
if (e.button == 2)
{
EagleEyeMapControl2.MousePointer = esriControlsMousePointer.esriPointerDefault;
}
}
else
{
EagleEyeMapControl2.MousePointer = esriControlsMousePointer.esriPointerDefault;
}
if (bCanDrag)
{
double Dx, Dy;
Dx = e.mapX - pMoveRectPoint.X;
Dy = e.mapY - pMoveRectPoint.Y;
pEnv.Offset(Dx,Dy);
pMoveRectPoint.PutCoords(e.mapX, e.mapY);
DrawRectangle(pEnv);
axMapControl1.Extent = pEnv;
}
}
/*判断鼠标是否是点击*/
private void EagleEyeMapControl2_OnMouseUp(object sender, IMapControlEvents2_OnMouseUpEvent e)
{
if (e.button == 1 && pMoveRectPoint != null)
{
if (e.mapX == pMoveRectPoint.X && e.mapY == pMoveRectPoint.Y)
{
axMapControl1.CenterAt(pMoveRectPoint);
}
bCanDrag = false;
}
}
/*此处缺失该函数 请从博主其他文章内查找···信息还来不及完全更新,抱歉*/
private IRgbColor GetRgbColor(int p, int p_2, int p_3)
{
throw new NotImplementedException();
}
其他:该代码我还写了数据视图与布局视图的切换,用不到可以删除该部分代码。
注意
鹰眼视图功能尚未完善,按照正常规划,应该小窗显示放大后数据视图中的全图,并且有矩形框显示,此部分内容改进,见后续文档
源码下载: