ArcObjects SDK 013 MapFrame
打开一个Mxd文件,可能包含一个或多个Map,每个Map都会放到一个MapFrame中,加载到PageLayout上。我们可以通过PageLayout继承的IGraphicsContainer循环判断获取各MapFrame对象。也可以调用IGraphicsContainer的FindFrame函数,传入对应的Map获取MapFrame对象。
MapFrame除了地图格网外,可设置的内容并不多。我们平常经常会设置的主要有边框、大小以及其要显示的坐标范围。设置的几种模式,我们可以在ArcMap的MapFrame属性界面中看到。
自动、固定比例尺以及固定范围,分别对应SDK中IMapFrame接口ExtentType属性的ExtentDefault、ExtentScale和ExtentBounds。
第一种模式是ArcMap默认的模式, MapFrame显示的地图范围、地图的显示比例尺以及MapFrame的大小都是可以随意调的。
第二种模式就是固定比例尺,固定后MapFrame的大小可以调节、显示的地图范围可以调节,但地图的比例尺是固定不变的。
第三种模式是固定地图显示范围,但MapFrame的大小是可以调节的,但只能等比例调节。调节MapFrame的大小调节后,因为显示的地图范围固定,所以比例尺会做对应的变化。
以上三种模式均可以在ArcMap上测试,看设置后,ArcMap有什么变化。例如第二种模式设置后,工具栏上的比例尺显示框以及和放大缩小相关的按钮都变成了不可用的灰色,,地图只能平移,不能放大缩小。第三种模式下,地图就被固定住了,只能显示指定范围,地图既不能放大缩小,也不能平移,大小也只能按照比例调整。
一般在用代码精确出图的时候,我习惯使用第三种模式,即在固定比例尺的情况下,设置要出图的地理范围,然后用范围乘以比例尺,计算出MapFrame需要呈现的大小,设置给MapFrame。这样就可以得到最合适大小的MapFrame,还可以精确的把出图范围固定住,并防止用户误操作,把地图放大缩小或平移。
很多时候,我们会先计算出主MapFrame的大小,然后四个方向扩2-5cm,得到Page的大小。例如我们计算出MapFrame,高为15cm,宽为20cm,上部留5cm放标题和指北针,下方留5cm放比例尺和图例等,左右各留3cm的空白。那么Page的大小可设置为高为25cm,宽为26cm,而MapFrame的位置设置为3,5。这样MapFrame就位于了Page的正中间,且距上下左右的距离分别位5cm、5cm、3cm和3cm。如下图所示。
由于本图,我们设置的Page的单位是mm,所以设置值的时候,设置的是30和50。我们修改的Page的边界样式为蓝色虚线,默认位黑色实线。
MapFrame继承了IMapGrids接口,该接口为IMapGrid集合,管理在MapFrame上的绘制的格网,包括经纬网、公里网等。MapFrame可以同时显示多个地图网格。
IMapGrid包含的可设置信息比较多,但一般设置的时候,我们主要关心格网周边的标注、网格线以及网格间隔值。我们在ArcMap中为一个MapFrame设置网格,并打开其属性信息,如下图所示。
平常我们使用,并且关心的包括Axex、Labels、Lines以及Intervals四个标签,分别是轴信息、文字标注信息、网格线信息以及间隔信息。
回到SDK,和网格相关的几个比较重要的接口包括IMapGrid和IMeasuredGrid。IMapGrid定义如下。
基本上IMapGrid涵盖了Axex、Labels、Lines三个标签的信息。IMapGrid接口定义的属性基本上能和三个标签页中的设置框对应的上。IMeasuredGrid接口主要用来设置起始计算坐标以及网格间隔。该接口定义如下。
该接口和Intervals标签页中设置的内容是对应着的。添加经纬网的代码如下。
IGraphicsContainer myGraphicsContainer = pPageLayout as IGraphicsContainer; IActiveView myActiveView = pPageLayout as IActiveView; IMap myMap = myActiveView.FocusMap; IMapFrame myMapFrame = myGraphicsContainer.FindFrame(myMap) as IMapFrame; IMapGrids myMapGrids = myMapFrame as IMapGrids; myMapGrids.ClearMapGrids(); if (this._MapGrid is IMgrsGrid == false && this.GridType == 0) { this._MapGrid = new GraticuleClass(); } else if (this._MapGrid is IProjectedGrid == false) { this._MapGrid = new MeasuredGridClass(); (this._MapGrid as IProjectedGrid).SpatialReference = this.BToLayoutDesign.MapFrameItem.SpatialReference; } this._MapGrid.Name = "MapGrid"; this._MapGrid.Visible = this.IsVisible; this._MapGrid.SetTickVisibility(this.IsShowTick, this.IsShowTick, this.IsShowTick, this.IsShowTick); if (this.IsShowTick == true) { this._MapGrid.TickLength = this.TickLength; ICartographicLineSymbol myTickLineSymbol = new CartographicLineSymbolClass(); myTickLineSymbol.Cap = esriLineCapStyle.esriLCSButt; myTickLineSymbol.Width = this.TickWidth; myTickLineSymbol.Color = ColorHelper.ConvertWPFToEngine(this.TickColor); this._MapGrid.TickLineSymbol = myTickLineSymbol; } ICartographicLineSymbol myGridLineSymbol = new CartographicLineSymbolClass(); myGridLineSymbol.Cap = esriLineCapStyle.esriLCSButt; myGridLineSymbol.Width = this.GridLineWidth; myGridLineSymbol.Color = ColorHelper.ConvertWPFToEngine(this.GridLineColor); this._MapGrid.LineSymbol = myGridLineSymbol; IMeasuredGrid myMeasuredGrid = this._MapGrid as IMeasuredGrid; myMeasuredGrid.FixedOrigin = true; myMeasuredGrid.XOrigin = this.XOrigin; myMeasuredGrid.YOrigin = this.YOrigin; myMeasuredGrid.XIntervalSize = this.XInterval; myMeasuredGrid.YIntervalSize = this.YInterval; IGridLabel myGridLabel = this._MapGrid.LabelFormat; IFontDisp myFontDisp = myGridLabel.Font; myFontDisp.Size = (decimal)this.LabelFontSize; myGridLabel.Font = myFontDisp; myGridLabel.Color = ColorHelper.ConvertWPFToEngine(this.LabelFontColor); myGridLabel.LabelOffset = this.LabelOffset; myGridLabel.LabelAlignment[esriGridAxisEnum.esriGridAxisLeft] = !this.IsLRLabelVertical; myGridLabel.LabelAlignment[esriGridAxisEnum.esriGridAxisRight] = !this.IsLRLabelVertical; this.UpdateLabelFormat(myGridLabel); this._MapGrid.LabelFormat = myGridLabel; myMapGrids.AddMapGrid(this._MapGrid);