问题分析
加载地图文档
加载地图文档的过程:先点击“打开”按钮,自动弹出电脑文件夹目录,再从中选取“.mxd”类型的地图文档;选中后点击确定,即可加载;加载时,地图内容显示在Map界面(利用MapControl控件),图层索引显示在TOC界面(利用TOCControl控件)。
放大
放大分为三种方法:矩形放大(拉框放大)、圆形放大、多边形放大。这四种方法看似不一样,但是其本质上都有相同点:放大后的视图为四种geometry的Envelope。因此放大时需要算出画出的几何图形的最小外包矩形即可作为最终视图的一部分。
缩小
与放大相似,首先判断是哪种缩小方法,判断后求出geometry的Envelope,接着计算缩小的比例和缩小后的视图中X、Y坐标的最大值和最小值,最后更新显示界面即可得到缩小后的视图结果。
WinForm界面搭建
设计Windows 窗体应用程序
新建项目
新建一个MapControl窗体应用程序项目(Engine):
窗体设计
MapControl窗体已经自带了很多常用的控件,包括TOCControl,MapControl,LicenseControl等,可以在此基础上添加或进行相应的修改。
读入.xmd文件功能
地图放大功能
在View选项内添加放大选项,并且在放大后增加:按矩形框放大、按圆形放大、按多边形放大三个选项。
地图缩小功能
在View选项内添加缩小选项,并且在缩小后增加:按矩形框缩小、按圆形缩小、按多边形缩小三个选项。
为控件绑定事件
为axMapControl1
绑定OnMouseDown
事件:
为各个ToolStripMenuItem
添加Click
事件(以按矩形框缩小为例):
添加功能
读入.xmd文件部分
使用OpenFileDialog
来过滤并读入文件,代码如下:
private void openXmlFileToolStripMenuItem_Click(object sender, EventArgs e)
{
IMapDocument pMxdMapDocument = new MapDocumentClass();
OpenFileDialog pMxdOpenFileDialog = new OpenFileDialog();
pMxdOpenFileDialog.Filter = "地图文档(*.mxd)|*.mxd";
if (pMxdOpenFileDialog.ShowDialog() == DialogResult.OK)
{
string xjmxdFilePath = pMxdOpenFileDialog.FileName;
if (axMapControl1.CheckMxFile(xjmxdFilePath))
{
axMapControl1.Map.ClearLayers();
axMapControl1.LoadMxFile(xjmxdFilePath);
}
}
axMapControl1.ActiveView.Refresh();
}
为了使TOCControl中的数据能显示出来,需要将TOCControl控件和MapControl控件通过接口连接,连接方法如下:
绘制图形缩小/放大部分
放大编程思路
首先定义放大的三种方法;接着在各种放大方法的按钮对应的代码中调用放大方法;然后再在OnMouseDowen事件中添加一个switch函数,选择对应的方法应当返回的geometry;最后判断Envelope的边界是否超过View的范围,如果没有超过,则进行放大操作。
缩小编程思路
首先利用switch语句判断缩小方法属于矩形缩小、圆形缩小和多边形缩小中的哪种;接着判断所画geometry是否为空,若为空,则返回空值,若非空则进行如下缩小操作:先算出缩小后视图的长和宽,其计算方法为:当前视图长或宽(当前视图长或宽/geometry的Envelope的长或宽),其中括号中的为缩小系数;接着计算出缩小后视图的x、y最小值:当前视图最小值-(geometry.Envelope的最小值-当前视图最小值)缩小系数;最后计算缩小后视图的最大值:最小值+缩小后视图的长或宽;最终更新视图即可得到缩小后的视图。
编程实现
首先定义一个toolAction
的变量来存储功能
private string toolAction;
在各个ToolStripMenuItem_Click
事件下编写功能,首先更改toolAction
变量的值,随后检查该功能是否被勾选,如果被勾选,则将axMapControl1_OnMouseDown
事件加入事件队列之中。
private void 按矩形框放大ToolStripMenuItem_Click(object sender, EventArgs e)
{
toolAction = "Rectangle Drag Zoom In";
if(this.按矩形框放大ToolStripMenuItem.Checked)
{
按矩形框放大ToolStripMenuItem.Checked = false;
this.axMapControl1.OnMouseDown -= new ESRI.ArcGIS.Controls.IMapControlEvents2_Ax_OnMouseDownEventHandler(this.axMapControl1_OnMouseDown);
}
else
{
按矩形框放大ToolStripMenuItem.Checked = true;
this.axMapControl1.OnMouseDown += new ESRI.ArcGIS.Controls.IMapControlEvents2_Ax_OnMouseDownEventHandler(this.axMapControl1_OnMouseDown);
}
}
private void 按矩形框缩小ToolStripMenuItem_Click(object sender, EventArgs e)
{
toolAction = "Rectangle Drag Zoom Out";
if (this.按矩形框缩小ToolStripMenuItem.Checked)
{
按矩形框缩小ToolStripMenuItem.Checked = false;
this.axMapControl1.OnMouseDown -= new ESRI.ArcGIS.Controls.IMapControlEvents2_Ax_OnMouseDownEventHandler(this.axMapControl1_OnMouseDown);
}
else
{
按矩形框缩小ToolStripMenuItem.Checked = true;
this.axMapControl1.OnMouseDown += new ESRI.ArcGIS.Controls.IMapControlEvents2_Ax_OnMouseDownEventHandler(this.axMapControl1_OnMouseDown);
}
}
private void 按多边形放大ToolStripMenuItem_Click(object sender, EventArgs e)
{
toolAction = "Geometry Drag Zoom In";
if (按多边形放大ToolStripMenuItem.Checked)
{
按多边形放大ToolStripMenuItem.Checked = false;
this.axMapControl1.OnMouseDown -= new ESRI.ArcGIS.Controls.IMapControlEvents2_Ax_OnMouseDownEventHandler(this.axMapControl1_OnMouseDown);
}
else
{
按多边形放大ToolStripMenuItem.Checked = true;
this.axMapControl1.OnMouseDown += new ESRI.ArcGIS.Controls.IMapControlEvents2_Ax_OnMouseDownEventHandler(this.axMapControl1_OnMouseDown);
}
}
private void 按多边形缩小ToolStripMenuItem_Click(object sender, EventArgs e)
{
toolAction = "Geometry Drag Zoom Out";
if (按多边形缩小ToolStripMenuItem.Checked)
{
按多边形缩小ToolStripMenuItem.Checked = false;
this.axMapControl1.OnMouseDown -= new ESRI.ArcGIS.Controls.IMapControlEvents2_Ax_OnMouseDownEventHandler(this.axMapControl1_OnMouseDown);
}
else
{
按多边形缩小ToolStripMenuItem.Checked = true;
this.axMapControl1.OnMouseDown += new ESRI.ArcGIS.Controls.IMapControlEvents2_Ax_OnMouseDownEventHandler(this.axMapControl1_OnMouseDown);
}
}
private void 按圆形放大ToolStripMenuItem_Click(object sender, EventArgs e)
{
toolAction = "Circle Drag Zoom In";
if (按圆形放大ToolStripMenuItem.Checked)
{
按圆形放大ToolStripMenuItem.Checked = false;
this.axMapControl1.OnMouseDown -= new ESRI.ArcGIS.Controls.IMapControlEvents2_Ax_OnMouseDownEventHandler(this.axMapControl1_OnMouseDown);
}
else
{
按圆形放大ToolStripMenuItem.Checked = true;
this.axMapControl1.OnMouseDown += new ESRI.ArcGIS.Controls.IMapControlEvents2_Ax_OnMouseDownEventHandler(this.axMapControl1_OnMouseDown);
}
}
private void 按圆形缩小ToolStripMenuItem_Click(object sender, EventArgs e)
{
toolAction = "Circle Drag Zoom Out";
if (按圆形缩小ToolStripMenuItem.Checked)
{
按圆形缩小ToolStripMenuItem.Checked = false;
this.axMapControl1.OnMouseDown -= new ESRI.ArcGIS.Controls.IMapControlEvents2_Ax_OnMouseDownEventHandler(this.axMapControl1_OnMouseDown);
}
else
{
按圆形缩小ToolStripMenuItem.Checked = true;
this.axMapControl1.OnMouseDown += new ESRI.ArcGIS.Controls.IMapControlEvents2_Ax_OnMouseDownEventHandler(this.axMapControl1_OnMouseDown);
}
}
为了避免大量重复的代码块出现,因此需要写一个缩小外接矩形的方法,代码如下:
private IEnvelope zoom_out(IEnvelope pEnvelop2)
{
double x_scale = axMapControl1.Extent.Width / pEnvelop2.Width;//XY尺寸
double y_scale = axMapControl1.Extent.Height / pEnvelop2.Width;
//新窗口的高度宽度=原地图窗口*比例
double width = axMapControl1.Extent.Width * x_scale;
double height = axMapControl1.Extent.Width * y_scale;
//找到窗口的最小值 即XY的最小值
double x_min = pEnvelop2.XMin - (pEnvelop2.XMin - axMapControl1.Extent.XMin) * x_scale;
double y_min = pEnvelop2.YMin - (pEnvelop2.YMin - axMapControl1.Extent.YMin) * y_scale;
//取矩形框的取最大值
double x_max = x_min + width;
double y_max = y_min + height;
//新的envelop
pEnvelop2.PutCoords(x_min, y_min, x_max, y_max);
return pEnvelop2;
}
在axMapControl1_OnMouseDown
事件中,使用switch case
语句来实现不同的功能:
private void axMapControl1_OnMouseDown(object sender, IMapControlEvents2_OnMouseDownEvent e)
{
switch (toolAction)
{
case "Rectangle Drag Zoom In":
IEnvelope pEnvelop = axMapControl1.TrackRectangle();
if (pEnvelop == null | pEnvelop.IsEmpty || pEnvelop.Height == 0 || pEnvelop.Width == 0)//判断外接矩形是否为空
{
return;
}
axMapControl1.Extent = pEnvelop;
break;
case "Rectangle Drag Zoom Out":
IEnvelope pEnvelop2 = axMapControl1.TrackRectangle();
if (pEnvelop2 == null || pEnvelop2.IsEmpty || pEnvelop2.Height == 0 || pEnvelop2.Width == 0)
{
return;
}
IEnvelope pEnvelop2_1 = zoom_out(pEnvelop2);
axMapControl1.Extent = pEnvelop2_1;
axMapControl1.Refresh();
break;
case "Geometry Drag Zoom In":
IGeometry IG1 = axMapControl1.TrackPolygon();
IEnvelope pEnvelop3 = IG1.Envelope;
if (pEnvelop3 == null | pEnvelop3.IsEmpty || pEnvelop3.Height == 0 || pEnvelop3.Width == 0)//判断外接矩形是否为空
{
return;
}
axMapControl1.Extent = pEnvelop3;
break;
case "Geometry Drag Zoom Out":
IGeometry IG2 = axMapControl1.TrackPolygon();
IEnvelope pEnvelop4 = IG2.Envelope;
if (pEnvelop4 == null | pEnvelop4.IsEmpty || pEnvelop4.Height == 0 || pEnvelop4.Width == 0)//判断外接矩形是否为空
{
return;
}
IEnvelope pEnvelop4_1 = zoom_out(pEnvelop4);
axMapControl1.Extent = pEnvelop4_1;
axMapControl1.Refresh();
break;
case "Circle Drag Zoom In":
IGeometry IG3 = axMapControl1.TrackCircle();
IEnvelope pEnvelop5 = IG3.Envelope;
if (pEnvelop5 == null | pEnvelop5.IsEmpty || pEnvelop5.Height == 0 || pEnvelop5.Width == 0)//判断外接矩形是否为空
{
return;
}
axMapControl1.Extent = pEnvelop5;
break;
case "Circle Drag Zoom Out":
IGeometry IG4 = axMapControl1.TrackCircle();
IEnvelope pEnvelop6 = IG4.Envelope;
if (pEnvelop6 == null | pEnvelop6.IsEmpty || pEnvelop6.Height == 0 || pEnvelop6.Width == 0)//判断外接矩形是否为空
{
return;
}
IEnvelope pEnvelop6_1 = zoom_out(pEnvelop6);
axMapControl1.Extent = pEnvelop6_1;
axMapControl1.Refresh();
break;
}
}
运行结果
读入.mxd文档
选择文件:
读入.mxd文档的结果:
按矩形框放大
拖拽一个矩形框:
按矩形框放大结果:
按矩形框缩小
拖拽一个矩形框:
按矩形框缩小结果:
按圆形放大
拖拽一个圆形
按圆形放大结果
按圆形缩小
拖拽一个圆形
按圆形缩小结果
按多边形放大
绘制一个多边形:
按多边形放大结果:
按多边形缩小
绘制一个多边形:
按多边形缩小结果:
分析
MapControl和TOCControl之间的关系,通过那个接口实现关联?
TOCControl控件相当于ArcMap中左侧的目录树,需要与一个“伙伴控件”协同工作,可以是MapControl、PageLayoutControl、SceneControl或者GlobeControl,通过ITOCBuddy
接口连接。
伙伴控件的设置可通过TOCControl属性对话框或用SetBuddyControl方法通过编程设置,
private void Form1_Load(object sender, EventArgs e)
{
axTOCControl1.SetBuddyControl(axMapControl1);
}
TOCControl控件支持Buddy
,SetBuddyControl()
将MapControl设置为伙伴控件,使得两者可以协同工作。