開啟一個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);