959
技術社區[雲棲]
ArcGIS Engine開發入門教程
利用ArcGIS Engine、VS .NET和Windows控件開發GIS應用
Dixon整理
此過程說明適合那些使用.NET建立和部署應用的開發者,它描述了使用ArcGIS控件建立和部署應用的方法和步驟。
你可以在下麵的目錄下找到相應的樣例程序:
<安裝目錄>/DeveloperKit/Samples/Developer_Guide_Scenarios/ ArcGIS_Engine/Building_an_ArcGIS_Control_Application/Map_Viewer
注:ArcGIS樣例程序不包含在ArcGIS Engine開發工具包“典型”安裝方式中。如果你沒有安裝它們,則可以重新運行開發工具包安裝向導,選擇“定製”或“修改”方式,並選擇軟件開發包下的樣例項進行安裝。
一、項目描述
利用視窗控件建立應用程序的目標是演示並使你熟悉在微軟Visual Studio .NET API中使用標準ArcGIS控件開發和部署GIS應用所需的步聚。本節中使用了Visual Studio .NET開發環境中的MapControl、 PageLayoutControl、TOCControl和ToolbarControl等視窗控件。COM、Java和C++程序員應該參考如下章節:利用ActiveX建立應用程序、利用可視化JavaBeans建立應用程序、建立命令行方式的Java應用和建立命令行方式的C++應用。
本節演示了創建查看ArcMap和ArcGIS桌麵應用圖形文檔的GIS應用程序的步驟。此節包含了以下技術:
l在微軟Visual Studio .NET中加載和嵌入ArcGIS控件。
l向PageLayoutControl和MapControl中加載圖形文檔。
l設置ToolbarControl和TOCControl的綁定控件。
l處理窗口縮放。
l向ToolbarControl添加ArcGIS Engine命令和工具。
l創建彈出式菜單
l在TOCControl中管理標簽編輯
l在MapControl中繪製圖形。
l為MapControl、PageLayoutControl和ToolbarControl創建定製工具。
l用戶化ToolbarControl。
l在Windows操作係統中部署應用。
二、概述
本方案使用微軟Visual Studio .NET開發環境加以實現,並使用了ESRI interop程序集(Interop Assemblies),它服務於被放置在.NET窗體上的、位於.NET 窗體控件(.NET Windows Controls)中的ArcGIS控件,這些程序集在托管的.NET代碼和非托管的COM代碼之間起了橋梁作用。對COM ArcGIS控件(COM ArcGIS Controls)成員的引用都要經過Interop程序集,然後到達實際的COM對象。同樣,也從COM對象經過Interop程序集到達.NET應用程序。每個ArcGIS Engine控件具有方法、屬性與事件,它們能夠被控件嵌入的容器(如,.NET窗體)訪問。每個控件對象及其功能可以與其他ESRI ArcObjects和自定義控件組合使用,創建用戶化的客戶應用程序。
此方案是使用了C#和Visual Basic .NET兩種語言創建,但以下技術實現集中傾向於C#方案。許多開發者可能會感覺用Visual Basic .NET更舒服,那是因為他們已經比較熟悉Visual Basic 6.0代碼,然而,對於Java和C++程序員來說,他們將會覺得對C#程序語言的語法更熟悉。無論你使用哪種開發環境,對於使用ArcGIS控件的好壞既依賴於你的編程環境技術,也依賴於你所掌握的ArcObjects技術。
在本方案中,使用ToolbarControl、TOCControl、PageLayoutControl和MapControl來為應用程序提供用戶界麵。這些ArcGIS控件與其他ArcObjects和ArcGIS Engine命令被開發者一起使用,用來創建一個GIS視窗應用。
三、設計
此方案在設計時,首先強調了ArcGIS 控件如何互相之間進行交互,其次,向開發者解釋說明了ArcGIS 控件對象模型的一部分。
每個.NET ArcGIS Engine控件包含有一套能夠被嵌入其內的窗口即時訪問的屬性頁。這些屬性些為控件屬性和方法的選擇提供了捷徑,並且允許開發者不寫任何代碼即可創建一個應用程序。本方案並沒有使用屬性頁,而是采用寫代碼的方式建立應用程序。關於屬性頁的更進一步的信息,請參考ArcGIS開發幫助(ArcGIS Developer Help)。
四、條件需求
要順利地完成以下方案,你需要以下條件(對於部署的需求將在後續的部署章節涉及到):
l安裝具有授權文件的ArcGIS Engine開發工具包(Developer Kit),使之能夠用於開發。
l安裝有微軟Visual Studio .NET 2003開發環境和微軟.NET Framework 1.1及其相應協議。
l熟悉微軟Windows操作係統和Microsoft Visual Studio .NET的工作知識,會用C#或Visual Basic .NET編程語言。當然,此方案中提供了一些如何在Microsoft Visual Studio .NET中使用ArcGIS控件的信息,但它不能替代對開發環境的培訓。
l不需要對ESRI其它軟件有足夠的經驗,但如果以前對ArcObjects有所接觸並對ArcGIS應用(如,ArcCatalog,ArcMap)有一個基本了解,則對於開發更有利。
l訪問來自本方案的樣例數據和代碼,它位於:
<安裝目錄>/DeveloperKit/Samples/Developer_Guide_Scenarios/ ArcGIS_Engine/Building_an_ArcGIS_Control_Application/Map_Viewer
本方案中使用到的控件和庫如下:
lAxMapControl |
lAxTOCControl |
lAxPageLayoutControl |
lAxToolbarControl |
lESRI.ArcGIS.Carto |
lESRI.ArcGIS.System |
lESRI.ArcGIS.Display |
lESRI.ArcGIS.SystemUI |
lESRI.ArcGIS.Geometry |
lESRI.ArcGIS.Utility |
lesriMapControl |
lesriTOCControl |
lesriPageLayoutControl |
lesriToolbarControl |
五、實現
下麵的實現過程中提供了你成功完成方案所需所有代碼。假設你對於開發環境已經有了一定的知識,所以下麵沒有逐步地詳細介紹如何用Microsoft Visual Studio .NET開發應用。
(一)加載ArcGIS控件
在你為應用程序編寫代碼之前,應該先將應用程序將用到的ArcGIS控件和其他ArcGIS Engine庫引用裝載到開發環境之中。
1.啟動Visual Studio .NET,並從新建項目對話框中創建一個新的Visual C# “Windows應用程序”項目。
2.將項目命名為“Controls”,並選擇位置存取該項目。
3.在“工具箱”的“Windows窗體”標簽欄中單擊右鍵,然後從上下文菜單中選擇“添加/移除項(I)…”。
4.在“自定義工具箱”中選擇“.NET Framework組件”,並複選“AxMapControl”,“AxPageLayoutControl”,“AxTOCControl”和“AxToolbarControl”,單擊確定按鈕。這樣所選擇的控件將顯示在工具箱的Windows窗體標簽欄中。
5.單擊項目菜單,並選擇“添加引用(R)…”。
6.在添加引用對話框中,雙擊“ESRI.ArcGIS.Carto”,“ESRI.ArcGIS.Display”,“ESRI.ArcGIS.Geometry”,“ESRI.ArcGIS.System”,“ESRI.ArcGIS.SystemUI”,“ESRI.ArcGIS.Utility”。單擊確定。
注:對於ESRI .NET程序集,將通過具體實例來說明,並使用.NET框架提供的COM傳送服務從你的C#項目中調用ESRI對象庫中的實體對象。
(二)在容器中嵌入ArcGIS控件
在你能夠訪問每個控件的事件、屬性和方法之前,需要將控件嵌入到.NET容器中。一旦將控件嵌入窗體內,它們將圖形化應用程序的用戶界麵。
1.在設計模式下打開.NET窗體。
2.雙擊工具箱Windows標簽欄中的AxMapControl控件,將MapControl加入到窗體上。
3.再將AxPageLayoutControl、AxTOCControl和AxToolbarControl如上添加到窗體中。
4.重新調整窗體上各個控件的大小和位置,調整結果如下所示。
5.在窗體上雙擊顯示窗體代碼窗口,在代碼窗口的頂部增加“using”命令:
using System;
using System.Windows.Forms;
// ArcGIS Engine引用
using ESRI.ArcGIS.SystemUI;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.ToolbarControl;
using ESRI.ArcGIS.TOCControl;
注:需注意C#是區分大小寫的。當你鍵入“ESRI.”時,智能敏感的自動完成功能將允許你通過按Tab鍵完成下一節。
(三)加載Map文檔到MapControl與PageLayoutControl
單獨的數據層或者使用ArcMap、ArcGIS桌麵應用程序產生的圖形文檔,能夠被加載到MapControl和PageLayoutControl中。你可以加載樣例圖形文檔,或者加載你自己的圖形文檔。後麵你將增加一個瀏覽圖形文檔的對話框。
1.選擇Form_Load事件,並輸入下列代碼(如果你使用你自己的圖形文檔,要替換為正確的文件名):
// 使用相對路徑向PageLayoutControl加載一個圖形文檔
string filename = @"../../../../../../../../Data//ArcGIS_Engine_Developer_Guide//gulf of st. lawrence.mxd";
if ( axPageLayoutControl1.CheckMxFile(filename) )
{
axPageLayoutControl1.LoadMxFile(filename, "");
}
2.在設計模式顯示窗體並從屬性窗選擇axPageLayoutControl1控件,顯示axPageLayoutControl事件。在OnPageLayoutReplaced事件上雙擊向代碼窗口添加該事件的處理函數。
3.在axPageLayoutControl1_OnPageLayoutReplaced事件中鍵入以下向MapControl加載樣例圖形文檔的代碼。當文檔被裝載入PageLayoutControl時OnPageLayoutReplaced事件將會被觸發。
privatevoid axPageLayoutControl1_OnPageLayoutReplaced(object sender, ESRI.ArcGIS.PageLayoutControl.IPageLayoutControlEvents_OnPageLayoutReplacedEvent e)
{
// 加載同樣的文檔到MapControl
axMapControl1.LoadMxFile(axPageLayoutControl1.DocumentFilename, null, null);
// 設置MapControl顯示範圍至數據的全局範圍
axMapControl1.Extent = axMapControl1.FullExtent;
}
(四)設置ToolbarControl與TOCControl控件的綁定控件
對於此應用程序,TOCControl和ToolbarControl控件將與PageLayoutControl相互協作,而不是MapControl。為此PageLayoutControl必須設置為綁定控件。TOCControl使用綁定的ActiveView顯示圖形、圖層和符號。而位於ToolbarControl上的任何命令、工具或菜單項會受綁定控件的顯示影響。
1.在Form_Load事件中的加載文檔代碼的後麵鍵入以下紅色部分內容:
privatevoid Form1_Load(object sender, System.EventArgs e)
{
// 使用相對路徑向PageLayoutControl加載一個圖形文檔
string filename = @"../../../../../../../../Data//ArcGIS_Engine_Developer_Guide//gulf of st. lawrence.mxd";
if ( axPageLayoutControl1.CheckMxFile(filename) )
{
axPageLayoutControl1.LoadMxFile(filename, "");
}
// 設置綁定控件
axTOCControl1.SetBuddyControl(axPageLayoutControl1);
axToolbarControl1.SetBuddyControl(axPageLayoutControl1);
}
2.生成並運行應用程序。圖形文檔被加載到PageLayoutControl,並且TOCControl列出了圖形文檔中的數據圖層。使用TOCControl通過複選和取消複選框控製圖層的可見性。默認地,圖形文檔的焦點圖(focus map)被裝入MapControl控件。在這種當前情況下,ToolbarControl控件顯示是空的,因為沒有為它添加任何命令。試著縮放窗體,你會注意到控件不會改變尺寸。
(五)處理窗口縮放
當窗口在運行時進行縮放時,PageLayoutControl和MapControl不會自動改變自身的尺寸。要改變控件的尺寸以便它們總是與匹配窗口的範圍,你必須將控件錨定在窗口上。如果PageLayoutControl或MapControl包含大量的數據,在窗口縮放期間重繪這些數據顯得相當重要。為了提高執行效率,你可以禁止數據重繪直到縮放操作完成後再重繪之。在縮放時,可以用一個可伸縮的位圖來替代重繪數據。
1.在設計模式顯示窗體並從屬性窗口中選擇axPageLayoutControl1。單擊Anchor屬性,將axPageLayoutControl1錨定在窗體的頂、左、底和右部。
2.錨定axMapControl控件到窗體的頂、左和底部。
3.在Form_Load事件的開頭增加以下代碼:
// 當縮放時禁止重繪
this.SetStyle(ControlStyles.EnableNotifyMessage, true);
4.向類增加以下常量:
publicclass Form1 : System.Windows.Forms.Form
{
// ……
privateconstint WM_ENTERSIZEMOVE = 0x231;
privateconstint WM_EXITSIZEMOVE = 0x232;
// ……
}
5.向重載的OnNotifyMessage方法中增加下列代碼:
protectedoverridevoid OnNotifyMessage(Message m)
{
base.OnNotifyMessage (m);
// 以下為手工添加的代碼
if ( m.Msg == WM_ENTERSIZEMOVE)
{
axMapControl1.SuppressResizeDrawing(true, 0);
axPageLayoutControl1.SuppressResizeDrawing(true, 0);
}
elseif ( m.Msg == WM_EXITSIZEMOVE)
{
axMapControl1.SuppressResizeDrawing(false, 0);
axPageLayoutControl1.SuppressResizeDrawing(false, 0);
}
}
6.生成並運行應用程序,試著縮放窗口。
注:禁止縮放時重畫方法是通過檢查發送到窗體的Windows消息工作的。當窗口開發縮放時,Windows發送WM_ENTERSIZEMOVE窗口消息。此時,我們禁止在MapControl和PageLayoutControl上繪製圖形,而是使用“stretchy bitmap”繪製。當Windows發送WM_EXITSIZEMOVE消息時,窗體結束縮放,這時我們全部重繪新的範圍。
(六)向ToolbarControl增加命令
ArcGIS Engine提供了120多個命令和工具,它們與MapControl、PageLayoutControl和ToolbarControl直接相互協作。這些命令和工具為你提供了大量的經常使用的地圖導航、圖形管理、地物選擇等方麵的GIS功能。現在將在你的應用程序中增加這些命令和工具的一部分。
1.在Form_Load事件中的加載文檔代碼之前添加如下代碼。
// 增加打開檔命令
string progID;
progID = "esriControlToolsGeneric.ControlsOpenDocCommand";
axToolbarControl1.AddItem(progID, -1, -1, false, 0,
esriCommandStyles.esriCommandStyleIconOnly);
// 增加PageLayout導航命令
progID = "esriControlToolsPageLayout.ControlsPageZoomInTool";
axToolbarControl1.AddItem(progID, -1, -1, true, 0,
esriCommandStyles.esriCommandStyleIconOnly);
progID = "esriControlToolsPageLayout.ControlsPageZoomOutTool";
axToolbarControl1.AddItem(progID, -1, -1, true, 0,
esriCommandStyles.esriCommandStyleIconOnly);
progID = "esriControlToolsPageLayout.ControlsPagePanTool";
axToolbarControl1.AddItem(progID, -1, -1, true, 0,
esriCommandStyles.esriCommandStyleIconOnly);
progID = "esriControlToolsPageLayout.ControlsPageZoomWholePageCommand";
axToolbarControl1.AddItem(progID, -1, -1, true, 0,
esriCommandStyles.esriCommandStyleIconOnly);
progID = "esriControlToolsPageLayout.ControlsPageZoomPageToLastExtentBackCommand";
axToolbarControl1.AddItem(progID, -1, -1, true, 0,
esriCommandStyles.esriCommandStyleIconOnly);
progID = "esriControlToolsPageLayout.ControlsPageZoomPageToLastExtentForwardCommand";
axToolbarControl1.AddItem(progID, -1, -1, true, 0,
esriCommandStyles.esriCommandStyleIconOnly);
// 增加地圖導航命令
progID = "esriControlToolsMapNavigation.ControlsMapZoomInTool";
axToolbarControl1.AddItem(progID, -1, -1, true, 0,
esriCommandStyles.esriCommandStyleIconOnly);
progID = "esriControlToolsMapNavigation.ControlsMapZoomOutTool";
axToolbarControl1.AddItem(progID, -1, -1, true, 0,
esriCommandStyles.esriCommandStyleIconOnly);
progID = "esriControlToolsMapNavigation.ControlsMapPanTool";
axToolbarControl1.AddItem(progID, -1, -1, true, 0,
esriCommandStyles.esriCommandStyleIconOnly);
progID = "esriControlToolsMapNavigation.ControlsMapFullExtentCommand";
axToolbarControl1.AddItem(progID, -1, -1, true, 0,
esriCommandStyles.esriCommandStyleIconOnly);
// 使用相對路徑向PageLayoutControl加載一個圖形文檔
// ……
2.生成並運行應用程序。現在ToolbarControl包含了ArcGIS Engine命令和工具,你可以使用它們導航加載到PageLayoutControl中的圖形文檔。使用頁麵布局命令對當前的頁麵布局進行導航控製,要對存在於數據框架中的數據進行導航則使用地圖命令。利用找開文檔命令可以瀏覽並加載其他的圖形文檔。
(七)給PageLayoutControl添加彈出式菜單
與給跟綁定控件協作的ToolbarControl增加ArcGIS Engine命令一樣,按照前麵的步驟,你也可以從ArcGIS Engine命令創建彈出式菜單。下麵將向你的應用程序中增加與PageLayoutControl協作的彈出式菜單。當在PageLayoutControl可視區域點擊鼠標右鍵的時候,彈出式菜單將顯示。
1.向類中添加如下的成員變量(紅色部分):
publicclass Form1 : System.Windows.Forms.Form
{
private ESRI.ArcGIS.MapControl.AxMapControl axMapControl1;
private ESRI.ArcGIS.PageLayoutControl.AxPageLayoutControl axPageLayoutControl1;
private ESRI.ArcGIS.TOCControl.AxTOCControl axTOCControl1;
private ESRI.ArcGIS.ToolbarControl.AxToolbarControl axToolbarControl1;
private IToolbarMenu m_ToolbarMenu = new ToolbarMenuClass(); // 彈出式菜單
// ……
2.在Form_Load事件中向ToolbarControl增加命令代碼的後麵加載文檔代碼的前麵增加如下代碼。
privatevoid Form1_Load(object sender, System.EventArgs e)
{
// 前麵是增加地圖導航的代碼……
// 共享ToolbarControl的命令池
m_ToolbarMenu.CommandPool = axToolbarControl1.CommandPool;
// 向ToolbarMenu增加命令
progID = "esriControlToolsPageLayout.ControlsPageZoomInFixedCommand";
m_ToolbarMenu.AddItem(progID, -1, -1, false,
esriCommandStyles.esriCommandStyleIconAndText);
progID = "esriControlToolsPageLayout.ControlsPageZoomOutFixedCommand";
m_ToolbarMenu.AddItem(progID, -1, -1, false,
esriCommandStyles.esriCommandStyleIconAndText);
progID = "esriControlToolsPageLayout.ControlsPageZoomWholePageCommand";
m_ToolbarMenu.AddItem(progID, -1, -1, false,
esriCommandStyles.esriCommandStyleIconAndText);
progID = "esriControlToolsPageLayout.ControlsPageZoomPageToLastExtentBackCommand";
m_ToolbarMenu.AddItem(progID, -1, -1, true,
esriCommandStyles.esriCommandStyleIconAndText);
progID = "esriControlToolsPageLayout.ControlsPageZoomPageToLastExtentForwardCommand";
m_ToolbarMenu.AddItem(progID, -1, -1, false,
esriCommandStyles.esriCommandStyleIconAndText);
// 設置與PageLayoutControl掛接
m_ToolbarMenu.SetHook(axPageLayoutControl1);
// 後麵是加載圖形文檔的代碼……
// ……
3.在設計模式顯示窗體並從屬性窗口中選擇axPageLayoutControl1,顯示axPageLayoutControl事件。雙擊OnMouseDown事件,向代碼窗口中增加事件處理代碼。
4.在axPageLayoutControl1_OnMouseDown事件中增加如下代碼:
privatevoid axPageLayoutControl1_OnMouseDown(object sender, ESRI.ArcGIS.PageLayoutControl.IPageLayoutControlEvents_OnMouseDownEvent e)
{
// 彈出ToolbarMenu
if ( e.button == 2)
{
m_ToolbarMenu.PopupMenu(e.x, e.y, axPageLayoutControl1.hWnd);
}
}
5.生成並運行應用程序。在PageLayoutControl的顯示區域單擊右鍵以顯示彈出菜單,並為頁麵布局導航。
(八)在TOCControl中控製標簽編輯
TOCControl默認允許用戶自動地切換圖層的可見性並改變顯示在目錄表中的名稱。你可以增加代碼防止用戶在編輯名稱時輸入空的字符串。
1.在Form_Load事件的開始增加下列代碼。
privatevoid Form1_Load(object sender, System.EventArgs e)
{
// 當縮放時禁止重繪
this.SetStyle(ControlStyles.EnableNotifyMessage, true);
// 設置標簽編輯為手動方式
axTOCControl1.LabelEdit = esriTOCControlEdit.esriTOCControlManual;
// 後麵是加載文檔代碼
// ……
2.在設計模式顯示窗體並從屬性窗口選擇AxTOCControl1控件,顯示AxTOCControl事件。雙擊OnEndLabelEdit向代碼窗口添加事件處理函數。
3.在axTOCControl1_OnEndLabelEdit事件中添加以下代碼:
privatevoid axTOCControl1_OnEndLabelEdit(object sender, ESRI.ArcGIS.TOCControl.ITOCControlEvents_OnEndLabelEditEvent e)
{
// 禁止在編輯標簽時鍵入空字串
string newLabel = e.newLabel;
if ( newLabel.Trim() == "" )
{
e.canEdit = false;
}
}
4.生成並生成應用程序。編輯TOCControl控件的地圖、圖層、標題或圖例類的標簽,在其上點擊一次,然後再點一次調用標簽編輯。試著用空字串替代標簽。在編輯期間,你可以隨時使用鍵盤上的ESC鍵取消編輯。
(九)在MapControl上繪製圖形
你可以將MapControl作為縮略圖窗體使用,並在其上繪製顯示PageLayoutControl內的焦點地圖的當前範圍。當你瀏覽PageLayoutControl數據框架內的數據時,你將看到縮略圖窗口也進行了更新。
注:使用地圖導航工具導航焦點圖(活動圖)將改變PageLayoutControl中焦點地圖的範圍並引起MapControl更新。使用頁麵布局工具導航頁麵布局將改變頁麵布局的範圍(不是PageLayoutControl中的焦點圖的範圍),而MapControl將不更新。
1.向類中增加下列成員變量:
publicclass Form1 : System.Windows.Forms.Form
{
private ESRI.ArcGIS.MapControl.AxMapControl axMapControl1;
private ESRI.ArcGIS.PageLayoutControl.AxPageLayoutControl axPageLayoutControl1;
private ESRI.ArcGIS.TOCControl.AxTOCControl axTOCControl1;
private ESRI.ArcGIS.ToolbarControl.AxToolbarControl axToolbarControl1;
private IToolbarMenu m_ToolbarMenu = new ToolbarMenuClass(); // 彈出式菜單
private IEnvelope m_Envelope; // MapControl繪製的範圍
private Object m_FillSymbol; // 在MapControl上繪製範圍使用的符號
private ITransformEvents_VisibleBoundsUpdatedEventHandler
visBoundsUpdatedE; // PageLayoutControl的焦點圖事件
注:聲明的變量visBoundsUpdatedE是一個托管。托管是一個類,它能夠擁有對指定方法的引用,並使它鏈接到一個特定的事件。在事件和方法之間的鏈接過程有時在.NET中被稱作wiring。
2.創建一個叫CreateOverviewSymbol的新函數。這個函數是創建你將在MapControl中使用的符號的地方,此符號是用來描述PageLayoutControl焦點地圖數據範圍的。函數中增加的代碼如下:
privatevoid CreateOverviewSymbol()
{
// 獲取IRGBColor接口
IRgbColor color = new RgbColor();
// 設置顏色屬性
color.RGB = 255;
// 獲取ILine符號接口
ILineSymbol outline = new SimpleLineSymbol();
// 設置線符號屬性
outline.Width = 1.5;
outline.Color = color;
// 獲取IFillSymbol接口
ISimpleFillSymbol simpleFillSymbol = new SimpleFillSymbolClass();
// 設置填充符號屬性
simpleFillSymbol.Outline = outline;
simpleFillSymbol.Style = esriSimpleFillStyle.esriSFSHollow;
m_FillSymbol = simpleFillSymbol;
}
3.從Form_Load事件在TOCControl標簽編輯代碼之前調用CreateOverviewSymbol函數。
privatevoid Form1_Load(object sender, System.EventArgs e)
{
// 當縮放時禁止重繪
this.SetStyle(ControlStyles.EnableNotifyMessage, true);
// 創建MapControl使用的符號
CreateOverviewSymbol();
// 下麵是標簽編輯處理代碼
// ……
}
4.增加下列OnVisibleBoundsUpdated函數。此函數將與地圖範圍改變時觸發的事件相連接,並用來設置新的地圖可見邊界範圍框。通過刷新MapControl,你強製它重繪其上顯示的圖形。
privatevoid OnVisibleBoundsUpdated(IDisplayTransformation sender, bool sizeChanged)
{
// 設置新的可見範圍
m_Envelope = sender.VisibleBounds;
// 改變MapControl的前景狀態
axMapControl1.ActiveView.PartialRefresh(
esriViewDrawPhase,esriViewForeground, null, null);
}
5.PageLayoutControl默認的事件接口是IPageLayoutControlEvents。這些事件不告訴我們數據邊框內的地圖範圍。為此你需要使用PageLayoutControl的焦點地圖的ItransformEvents接口。在PageLayoutControl_OnPageLayoutReplaced事件處理中的加載文檔代碼前麵增加以下代碼。
privatevoid axPageLayoutControl1_OnPageLayoutReplaced(object sender, ESRI.ArcGIS.PageLayoutControl.IPageLayoutControlEvents_OnPageLayoutReplacedEvent e)
{
// 獲取PageLayoutControl中焦點地圖的IActiveView對象
IActiveView activeView = (IActiveView)
axPageLayoutControl1.ActiveView.FocusMap;
// 捕捉PageLayoutControl的焦點圖的ITransformEvents事件
visBoundsUpdatedE = new ITransformEvents_VisibleBoundsUpdatedEventHandler(OnVisibleBoundsUpdated);
((ITransformEvents_Event)activeView.ScreenDisplay
.DisplayTransformation).VisibleBoundsUpdated += visBoundsUpdatedE;
// 獲取焦點圖的範圍
m_Envelope = activeView.Extent;
// 後麵是加載地圖文檔的代碼
// ……
6.在設計模式下顯示窗體並從屬性窗中選擇axMapControl1,顯示axMapControl事件。雙擊OnAfterDraw向代碼窗口中增加事件處理。
7.向axMapControl1_OnAfterDraw事件處理中增加以下代碼,使用前麵創建的符號繪製MapControl顯示邊框。
privatevoid axMapControl1_OnAfterDraw(object sender, ESRI.ArcGIS.MapControl.IMapControlEvents2_OnAfterDrawEvent e)
{
if ( m_Envelope == null)
{
return;
}
// 如果前景狀態被重繪
esriViewDrawPhase viewDrawPhase = (esriViewDrawPhase)e.viewDrawPhase;
if ( viewDrawPhase == esriViewDrawPhase.esriViewForeground )
{
IGeometry geometry = m_Envelope;
axMapControl1.DrawShape(geometry, ref m_FillSymbol);
}
}
生成並運行應用程序。使用你先前已經加好的地圖導航工具改變PageLayoutControl中焦點地圖的範圍。新的範圍被繪製在MapControl上。
(十)創建自定義工具
創建協同MapControl和PageLayoutControl一起運作的自定義命令和工具,與你或許已經做過的創建ESRI ArcMap應用程序命令非常相似。你將創建一個在PageLayoutControl鼠標點擊位置添加包含當天日期的文本元素的自定義工具。不管用何種方法,創建同MapControl和ToolbarControl協作的命令與同PageLayoutControl一樣。
這個自定義工具的相關代碼與其他本方案源代碼一樣很有用。如果你想要直接使用自定義命令,而不自己創建它,請直接到第24步。
1.從新建項目對話框創建一個新的Visual C# “類庫”項目。
2.將項目命名為“Commands”,並選擇保存位置存貯之。
3.單擊項目菜單並選擇“添加引用(R)…”。
4.在添加引用對話框中,複選“ESRI.ArcGIS.Carto”,“ESRI.ArcGIS.Display”,“ESRI.ArcGIS.Geometry”,“ESRI.ArcGIS.System”,“ESRI.ArcGIS.SystemUI”,“ESRI.ArcGIS..Utility”和“ESRI.ArcGIS.ControlCommands”。
5.在項目中增加一個類,名字叫AddDateTool。
6.點擊項目菜單並選擇添加現有項,瀏覽樣例源碼目錄並找到date.bmp文件將其加入到你的項目。
7.在解決方案資源管理器中點擊date.bmp在屬性窗口顯示其屬性。改變生成操作屬性為嵌入的資源。這張位圖將被用來作為命令按鈕的外觀。
8.改變AddDateTool的命名空間的名稱為CSharpDotNETCommands。
namespace CSharpDotNETCommands
{
……
注:要在Visual Basi .NET中改變命名空間的名稱,則在解決方案資源管理器的項目上點擊右鍵並選擇屬性,在項目屬性頁中選擇常規並改變根命名空間後,按確定。
9.在AddDateTool類代碼窗口的頂部增加以下引用。
using System;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.SystemUI;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.ControlCommands;
using ESRI.ArcGIS.Utility.BaseClasses;
using System.Runtime.InteropServices;
10.指定AddDateTool類繼承自ESRI BaseTool抽象類,並增加密封(sealed)類修飾。
publicsealedclass AddDateTool : BaseTool
{
……
注:抽象類是不能被實例化的類,通常僅包含部分實現代碼,或者不包含任何實現代碼。它們與接口密切相關;但與接口有明顯的區別,也就是說,一個類可能實現任意數量的接口,但它僅能夠從一個抽象類中繼承。繼承了ESRI BaseTool抽象類,你便可以比直接實現esriSystemUI ICommand和ITool接口更快速、簡便地創建命令和工具。
密封類修飾說明一個類不能被繼承。此類的設計是為了限製其他類從該類繼承。
11.向AddDateTool類的構造函數中增加下列代碼:
publicsealedclass AddDateTool : BaseTool
{
public AddDateTool()
{
// 獲取程序集中的資源數組
string[] res = GetType().Assembly.GetManifestResourceNames();
// 設置工具屬性
base.m_bitmap = new System.Drawing.Bitmap(
GetType().Assembly.GetManifestResourceStream(res[0]));
base.m_caption = "添加日期";
base.m_category = "CustomCommands";
base.m_message = "在頁麵布局中增加一個日期元素";
base.m_name = "CustomCommands_Add Date";
base.m_toolTip = "添加日期";
}
}
注:類構造函數是一個當類創建時被調用的方法。它可以用來初始化類成員變量。構造函數名與類名相同;與其他方法不同的是它沒有返回類型。
程序中隻個別地替換實現了位圖、標題、目錄、名稱、消息和提示方法,你可以設置從這此方法返回的值,且依賴於BaseTool類為這此方法提供的實現。其它的成員保留BaseTool類返回的默認值。
12.向AddDateTool類增加下列成員變量。
publicsealedclass AddDateTool : BaseTool
{
// HookHelper對象處理通過OnCreate事件的回調
private IHookHelper m_HookHelper = new HookHelperClass();
……
13.在類視圖窗口中,定位到BaseCommand類的OnCreate方法,右鍵點擊之顯示上下文菜單。選擇增加,然後重載並增加該方法至代碼窗口。
14.在重載的OnCreate方法中增加以下代碼。
publicoverridevoid OnCreate(object hook)
{
m_HookHelper.Hook = hook;
}
注:要在Visual Basic .NET中重載屬性和方法,從代碼窗口頂部的“Class Name”組合框中選擇“Overrides”,從“Method Name”組合框中選擇屬性或方法。
15.在類視圖中定位到BaseCommand類的Enabled屬性並在其上點擊右鍵顯示上下文菜單。選擇添加,然後點重寫增加該屬性至代碼窗口。
16.增加以下代碼,重寫BaseTool類的默認Enabled值。
publicoverridebool Enabled
{
get
{
// 設置使能屬性
if ( m_HookHelper.ActiveView != null )
{
returntrue;
}
else
{
returnfalse;
}
}
}
注:ICommand_OnCreate事件向命令工作的應用程序傳送一個句柄或回調。在這種情況下,它可以是MapControl,PageLayoutControl或ToolbarControl。除向OnCreate事件增加代碼外,你可以使用HookHelper判斷傳向命令的回調類型。命令或工具需要知道如何處理傳送的回調,所以必須對ArcGIS Control傳送的類型作檢查。HookHelper用來控件回調並返回ActiveView忽略的回調類型(MapControl、PageLayoutControl和ToolbarControl都是這樣)。
17.在類視圖中定位到BaseTool基類的OnMouseDown方法,並在其上點擊右鍵顯示上下文菜單。選擇添加,然後重載並增加該屬性至代碼窗口。
18.增加下列代碼,重載BaseTool類實現的默認OnMouseDown函數。
publicoverridevoid OnMouseDown(int Button, int Shift, int X, int Y)
{
// TODO: 添加 AddDateTool.OnMouseDown 實現
base.OnMouseDown (Button, Shift, X, Y);
// 獲取活動視圖
IActiveView activeView = m_HookHelper.ActiveView;
// 創建新的文本元素
ITextElement textElement = new TextElementClass();
// 創建文本符號
ITextSymbol textSymbol = new TextSymbolClass();
textSymbol.Size = 25;
// 設置文本元素屬性
textElement.Symbol = textSymbol;
textElement.Text = DateTime.Now.ToShortDateString();
// 對IElementQI
IElement element = (IElement) textElement;
// 創建頁點
IPoint point = new PointClass();
point = activeView.ScreenDisplay.DisplayTransformation.ToMapPoint(X, Y);
// 設置元素圖形
element.Geometry = point;
// 增加元素到圖形繪製容器
activeView.GraphicsContainer.AddElement(element, 0);
// 刷新圖形
activeView.PartialRefresh(esriViewDrawPhase.esriViewGraphics,
null, null);
}
19.ArcGIS Engine期望自定義命令是一個COM類;因此,你必須指定你所創建的.NET類也成為一個COM類,它是通過創建一個COM可調用包裝(callable wrapper)實現的。在解決方案資源管理器窗口中,在Commands項目上右擊鼠標鍵並從上下文菜單中選擇屬性。
20.在項目屬性頁對話框中選擇配置屬性;並點擊生成。在右麵的麵板中,改變為“為Com Interop注冊”為True,點確定。
注:設置“為Com Interop注冊”屬性為True會調用程序集注冊工具(Regasm.exe)。這將增加客戶端期望找到的類信息。