GIS二次開發實習(一)——鷹眼功能實現
學期末爲期2周的實習結束了,對實習要求所做 太湖水資源管理系統 的功能的實現一一做一個記錄,今天先來鷹眼部分(細節部分這裏就不說了看前面的文章(一))。
實現效果
實現步驟
(一)技術路線
(二)實現步驟
1功能分析
鷹眼,其功能是使用者在大比例尺進行瀏覽地圖時全局顯示地圖的一個小地圖窗口,爲使用者提供一個當前瀏覽地圖在全局地圖上的相對位置,所以我們分析得以下幾個功能。
- 1.1鷹眼窗口全局顯示關鍵圖層且不可縮放
加載地圖後鷹眼部分全局鎖定顯示地圖,併爲防止地圖信息過多,只顯示關鍵信息方便瀏覽。
axMapControl2.AutoMouseWheel = false;//使鼠標中鍵滾輪無效
- 1.2主圖平移縮放時與鷹眼圖中範圍框(紅框)的聯動
- a.主圖進行平移縮放時,在平移完成後將主圖所全局顯示的地圖地理座標範圍傳出。
- b.鷹眼圖監聽到該平移縮放事件,獲取到地圖主圖傳出的地圖地理座標範圍後,在對應鷹眼地圖上對應地圖地理座標顯示範圍框(紅框),實現鷹眼地圖的聯動。
- 1.3鷹眼範圍框(紅框)拖動使主題聯動
- a.在鷹眼部分點擊鼠標右鍵,範圍框(紅框)中心移至鼠標點擊中心,傳出範圍框(紅框)相對地圖地理座標範圍。
- b.主圖監聽到範圍框(紅框)的地圖地理座標範圍,將地圖全局縮放至改地理座標範圍,實現聯動。
- 1.4鷹眼中右鍵繪製範圍框(紅框)使主圖縮放到所框範圍
- a.鷹眼中左鍵拖動繪製範圍框(紅框),傳出範圍框所包含的地理座標範圍
- b.主圖中監聽到鷹眼中範圍框(紅框)傳來的地理座標範圍,在控件中全局顯示。
2添加鷹眼控件
-
(1)在設計視圖中,選擇splitcontainer控件,即有2個panl的那個容器,將其Dock屬性設爲Fill。再第二個SplitContainer控件拖到窗體的左窗格,並將其Orientation屬性設置爲Horizontal,將其Dock屬性也設爲Fill,如圖1。
圖1 -
(2)將TOCControl控件, 到splitcontainer2的panl1中,再將2個MapControl控件分別拖入SplitContainer1的Panel2中和SplitContainer2的Panel2中,操作完成後效果如圖2所示。
圖2
-
(3)在TOCControl1中右鍵選擇屬性,將buddy control設置爲axMapControl1,如圖3.
圖3 -
(4)從工具箱中選擇MapControl控件並拖到SplitContainer2的Panel2,作爲鷹眼控件。最終效果如圖4所示。
此外在有兩層splitcontainer中的axTOCControl1不能正常顯示圖層,所以在主窗體的Form1_Load_1事件中加入下如下代碼,保證axTOCControl1控件與axMapControl1控件連接並可顯示。
private void Form1_Load_1(object sender, EventArgs e) //綁定鷹眼窗體
{
MessageBox.Show("歡迎使用太湖流域水資源信息管理系統!請您先加載地圖");
try
{
axTOCControl1.SetBuddyControl(axMapControl1);
CreateOverviewSymbol(); //矩形框創建函數調用
}
catch { MessageBox.Show("請先加載地圖文件");}
}
3代碼的實現
- 3.1申明一個畫矩形框的函數,以便鷹眼中的範圍框(紅框)調用。代碼及詳細說明如下
private void CreateOverviewSymbol() //創建一個繪製矩形框的函數
{
IRgbColor iRgb = new RgbColorClass();//創建一個顏色對象,以便後面將顏色賦予線要素pOutline
iRgb.RGB = 0; //將黑色賦予iRgb顏色對象
ILineSymbol pOutline = new SimpleLineSymbolClass(); //創建線要素對象pOutline
pOutline.Color = iRgb; //將iRgb的顏色賦予線要素對象pOutline
pOutline.Width =2.3; //對線要素對象pOutline設置線的寬度
//將此面要素除了輪廓線之外沒有填充色,也就是中間透明的黑色輪廓線寬度爲2.3的矩形框
ISimpleFillSymbol pSimpleFS = new SimpleFillSymbolClass(); //創建帶填充屬性的面要素
pSimpleFS.Outline = pOutline; //將線要素pOutline的設置賦予面要素pSimpleFS的輪廓線pSimpleFS.Outline
pSimpleFS.Style = esriSimpleFillStyle.esriSFSHollow; //將pSimpleFS.Style面要素的填充方式,設置爲esri包裏定義的空(esriSFSHollow),到此矩形框就設置好了
oFillobject = pSimpleFS;//將可填充的面要素pSimpleFS的設置賦予在前面函數外設置的全局面要素變量(對象),以便後面用到和pSimpleFS的設置相同的面要素時直接調用
} //也就是將設好的矩形框模式賦予oFillobject
- 3.2 axMapControl1控件的OnMapReplaced事件主要是要說明在axMapControl1控件中的地圖文件更換後要執行的內容,代碼和詳解如下
private void axMapControl1_OnMapReplaced (object sender, IMapControlEvents2_OnMapReplacedEvent e)//axMapControl1控件的OnMapReplaced事件主要是要說明在axMapControl1控件中的地圖文件更換後要執行的內容
{
axMapControl2.AutoMouseWheel = false;//使鼠標中鍵滾輪無效
if (axMapControl1.DocumentMap != null)//判斷axMapControl1控件中加載的地圖文件是否爲空
{
axMapControl2.LoadMxFile(axMapControl1.DocumentFilename);//如果axMapControl1控件中加載的地圖文件不爲空,在axMapControl2控件中也加載相同的地圖文件
if (axMapControl2.get_Layer(0) == null) return;
for (int i = 0; i < 12; i++)//
將太湖水資源地圖的前8個次要要素圖層隱藏,顯示第9層以後的
{
if(i<8)axMapControl2.get_Layer(i).Visible = false;
if (i > 8) axMapControl2.get_Layer(i).Visible = true;
}
axMapControl2.Extent = axMapControl2.FullExtent; //將axMapControl2顯示的地圖範圍/視圖全局顯示
}
else { MessageBox.Show("空地圖"); }
}
- 3.3使鷹眼窗口中的地圖在界面改變使重新全局顯示地圖,代碼和詳解如下:
private void axMapControl2_OnExtentUpdated (object sender, IMapControlEvents2_OnExtentUpdatedEvent e)//使鷹眼窗口中的地圖在界面改變使重新全局顯示地圖
{
axMapControl2.Extent = axMapControl2.FullExtent; //將axMapControl2顯示的地圖範圍/視圖全局顯示
}
- 3.4 在鷹眼窗體上操作時繪製框和刷新地圖的代碼實現,詳解如下:
/// <summary>
/// 在鷹眼窗體上操作時繪製框和刷新地圖
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void axMapControl2_OnMouseDown (object sender, IMapControlEvents2_OnMouseDownEvent e)////axMapControl1控件的OnMouseDown事件主要是要說明在axMapControl1控件中的地圖文件更換後要執行的內容
{
if (e.button == 2)//判斷鼠標點擊是否是右鍵——右鍵畫紅框
{
pEn = axMapControl2.TrackRectangle();//如果是右鍵,將axMapControl2的TrackRectangle的繪製方法賦予之前創建的矩形要素pEn
axMapControl1.Extent = pEn;//將axMapControl1控件中鋪開地圖的位置與大小設置爲繪製的pEn矩形框選的地圖部分
axMapControl2.DrawShape(pEn, ref oFillobject);//將axMapControl2的繪製形狀的方法(DrawShape),設置爲以pEn爲形狀,oFillobject爲填充填充模式的方法
if (e.button == 1) //左鍵拖動紅框
{
Point_pSV_MouseDown = new PointClass(); //開始已定義的全局變量點對象Point_pSV_MouseDown,新建一個IPoint類型,以便下面將鼠標的落腳點賦予它
Point_pSV_MouseDown.PutCoords(e.mapX, e.mapY);//將鼠標在地圖上的橫縱座標賦予點對象Point_pSV_MouseDown
IEnvelope pEnvelope = this.axMapControl1.Extent;//將axMapControl1控件所顯示的地圖邊界形狀賦予新創建的pEnvelope
pEnvelope.CenterAt(Point_pSV_MouseDown); //將這個“矩形”中心移到鼠標所在axMapControl2控件中地圖的座標點點
axMapControl1.Extent = pEnvelope;//將移動後的矩形pEnvelope中所框的地圖顯示在axMapControl1控件中
this.axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, null);//將axMapControl1控件中的變化刷新顯示
//局部刷新
isTrackSV = true;//將全局bool變量isTrackSV 設置爲true,代表鼠標在拖動
if (pSViEnv == null)//判斷鼠標繪製的矩形框是否是否有移動反饋(pSViEnv是一個之前在函數外用IMoveEnvelopeFeedback接口創建的對象)
{
pSViEnv = new MoveEnvelopeFeedbackClass();//沒有就新建一個,相當於刷新
pSViEnv.Display = axMapControl2.ActiveView.ScreenDisplay;//再將axMapControl2新的顯示賦予 pSViEnv的顯示方法Display
pSViEnv.Symbol = (ISymbol)oFillobject;//將新的矩形pSViEnv的填充方法設置爲oFillobject的方法,不過得把oFillobject的類型轉換爲ISymbol
}
pSViEnv.Start(pEn, Point_pSV_MouseDown); //執行移動
}
}
}
- 3.5將主地圖窗口的邊框所框住地圖範圍傳遞給鷹眼窗口,代碼及詳解如下:
private void axMapControl1_OnAfterDraw (object sender, IMapControlEvents2_OnAfterDrawEvent e)////axMapControl1控件的OnAfterDraw事件主要是要說明在axMapControl1控件中的用鼠標拖動繪製後要執行的內容
{
esriViewDrawPhase viewDrawPhase = (esriViewDrawPhase)e.viewDrawPhase;//將鼠標按壓時拖動所繪製的的動態賦予esriViewDrawPhase接口新創建的 viewDrawPhase裏
if (viewDrawPhase == esriViewDrawPhase.esriViewForeground)//判斷鼠標按壓狀態下繪製的的動態是否賦予了viewDrawPhase
{
axMapControl2.DrawShape(pEn, ref oFillobject); //如果鼠標按壓狀態下繪製的的動態賦予了viewDrawPhase 就以pEn的形狀和繪製方式繪製圖形要素,這裏繪製的就是之前設置的矩形框pEn
}
}
- 3.6爲使鷹眼中範圍框保持連續,需每獲取移動實踐2次就重繪一次矩形框,代碼如下:
private void axMapControl2_OnMouseMove (object sender, IMapControlEvents2_OnMouseMoveEvent e)
{
if (isTrackSV)
{
moveCount++;
if (moveCount % 2 == 0) //因爲刷新,紅框消失→每移動2次就刷新一下,保持紅框的連續性
axMapControl2.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewForeground, null, null);
Point_pSV_MouseDown.PutCoords(e.mapX, e.mapY);
pSViEnv.MoveTo(Point_pSV_MouseDown);
}
// 如果不是左鍵按下就直接返回,代碼對應axMapControl2_OnMouseDown中的左鍵拖動紅框
if (e.button != 1) return;
IPoint pPoint = new PointClass();
pPoint.PutCoords(e.mapX, e.mapY);
this.axMapControl1.CenterAt(pPoint);
this.axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, null);
}
- 3.7當鬆開鼠標後,以鼠標鬆開的點爲矩形框的結束點繪製完成代碼如下
private void axMapControl1_OnMouseUp (object sender, IMapControlEvents2_OnMouseUpEvent e) //若鼠標結束繪製,即鬆開鼠標鍵……
{
if (pSViEnv != null)
{
pEn = pSViEnv.Stop();將此時矩形框的結束點賦予pEn
axMapControl1.Extent = pEn;
isTrackSV = false;
}
}
(三)實現效果
太湖水資源管理系統實現心得
- 先簡單說一下這個學期一個課程學完後因爲自己的基礎不行,還懵懵懂懂,對於代碼的編寫還是一竅不通,只能做到複製粘貼,而實習當中,經過幾天無憂無慮的代碼複製粘貼,加上在老師和同學的幫助下的編寫,自己對C#算是簡單入門了。雖然自己現在技術還不咋的,但是感覺自己成長的還是蠻多的,從窗口控件的佈置越來越流暢,到接口互操作的行行代碼的類型轉換,再到一些必要的邏輯語句嵌套,最後到整個程序的測試修改,最後還進行了UI的設計,自己設計的UI好幾個同學都喜歡,如果我很是開心,自己體驗了一次全套的輕便軟件的開發,對於技術類的工作也管中窺豹瞭解了幾分,話說還是挺有意思的,這種自己創造一種產品的感覺着實振奮人心!使自己對技術行業產生了些許興趣。
- 當然也得知道我們每一個人實現的功能,難易不同,雖然我在同學的幫助下實現了鷹眼,點選、框選、多邊形選擇要素,和UI設計,但其他小組成員的數據庫維護,和過程線繪製這部分更難的功能,我還沒來得及瞭解,課下得抓緊機會學習。