1. 功能概述
關於PIE SDK的功能開發,在我們的博客上已經分門別類的進行了展示,點擊PIESat博客就可以訪問,為了初學者入門,本章節將對從PIE SDK組件式二次開發如何搭建界面、如何綜合開發進行詳細的講解。
目錄樹圖
2. 功能實現
2.1.界面搭建
最終的界面如下圖所示:
圖1最終結果圖
2.1.1 新建項目
選擇“Window窗體應用程序”,設置程序的名稱和保存路徑即可。(新建完成后可以將程序的窗體名稱右鍵重命名為“FormMain”,,將窗體界面的屬性的Text設置名稱為“PIE應用程序”)
圖2新建項目
2.1.2 環境搭建
新建項目完成后,系統默認的環境解決方案配置是Debug 模式,解決方平台是Any CPU,這里可以進行將平台改為x86
圖3
圖4
添加引用:
圖5
步驟:右鍵點擊引用-》添加引用選擇框內常用的dll即可
圖6
圖7
2.1.3 菜單設計
第一步:從“工具箱”選擇“menuStrip”控件拖到窗體界面,然后依次在菜單欄中設置相應的模塊,並修改每個ToolStripMenuItem的屬性Name的值,例如“文件”,設置為“toolStripMenuItem_Menu”,其他的同理
圖8
第二步:在每一級模塊下展開子菜單,如下圖:
圖9
第三步:從工具箱選擇“toolStrip”控件,點擊下三角根據不同功能選擇不同類型的控件
圖10
2.1.4 主界面設計
第一步:添加容器splitContainer容器控件和labControl控件(添加容器之前要先添加狀態欄StatusStrip控件,否則界面的控件會出現重疊現象)
圖11
第二步:在右邊的pannel2里面從工具箱里添加一個TabControl控件,將Dock屬性設置為填充“Fill”;
然后右鍵TabControl控件修改屬性“Alignment”為“Bottom”,
修改屬性“Dock”為“Bottom”填充,使控件填充頁面
圖12
最后修改屬性,進入TabPage集合編輯器頁面,依次選擇左側的將tabPage1的Text修改為“地圖模式”,tabPage2的Text修改為“制圖模式”。然后確定。
圖13
2.1.5 狀態欄設計
在“StatusStrip”控件中,設計8個label,一個Combox為比例尺的值控件,地圖坐標和屏幕坐標的顯示值控件邊框顯示的屬性“BorderSides”設置為“All”
圖14. 狀態欄
注意:顯示比例尺下拉框不能直接的控件可以拖放,具體步驟如下:
第一步選擇SplitButton控件,第二步點擊下圖中的1指向的下三角,第三步點擊2旁邊的下三角,第四步,選擇新建Combox,3指向的選項,最后,點擊新建的Combox,復制Ctrl+C,然后點擊狀態欄進行粘貼,再把原來的splitButton刪除就可以。
圖15.比例尺下拉框控件
2.2.圖層樹如何和地圖和制圖模式控件關聯
TOCControl 為用戶提供了一個交互式的環境,如果 TOCControl 控件的伙伴控件是 MapControl 控件,當我們將 TOCControl 控件中圖層刪掉是,MapControl 控件中相應的圖層也會被刪掉。
當地圖視圖和制圖視圖都存在的時候,TocControl控件要與PageLayoutControl控件進行綁定,MapControl的map和PageLayoutControl的map關聯,這樣才能確保地圖視圖和制圖視圖的數據保持一致。
圖層樹控件tocComtrolMain,地圖控件mapControl1,制圖控件pageLayoutControl1,為了圖層樹和地圖進行關聯,地圖和制圖數據同步,所以將mapControl1的地圖和PageLayoutControl1的地圖進行綁定,將PageLayoutControl與圖層樹進行綁定。並進行地圖模式切換的事件功能設計
1 /// <summary> 2 /// 初始化函數 3 /// </summary> 4 private void InitFrm() 5 {//綁定 6 mapControl1.FocusMap = pageLayoutControl1.FocusMap; 7 tocControlMain.SetBuddyControl(pageLayoutControl1); 8 mapControl1.Activate(); 9 pageLayoutControl1.DeActivate(); 10 }
然后進行地圖模式和制圖模式切換事件,右鍵TabControl控件屬性,選擇事件,找到SelectIndexChange事件,進行
圖16
1 /// <summary> 2 /// 地圖模式和制圖模式切換按鈕 3 /// </summary> 4 /// <param name="sender"></param> 5 /// <param name="e"></param> 6 private void tabControl1_SelectedIndexChanged(object sender, EventArgs e) 7 { 8 if (tabControl1.SelectedIndex == 0) 9 { 10 ActivateMapControl(); 11 } 12 else if (tabControl1.SelectedIndex == 1) 13 { 14 ActivatePageLayoutControl(); 15 } 16 } 17 /// <summary> 18 /// 激活地圖模式 19 /// </summary> 20 private void ActivateMapControl() 21 { 22 pageLayoutControl1.DeActivate(); 23 mapControl1.Activate(); 24 mapControl1.PartialRefresh(ViewDrawPhaseType.ViewAll); 25 } 26 /// <summary> 27 /// 激活制圖模式 28 /// </summary> 29 private void ActivatePageLayoutControl() 30 { 31 mapControl1.DeActivate(); 32 pageLayoutControl1.Activate(); 33 pageLayoutControl1.PartialRefresh(ViewDrawPhaseType.ViewAll); 34 }
2.3.功能的實現(部分功能為例)
2.3.1 Pmd地圖文檔數據的加載

1 /// <summary> 2 /// 新建pmd文件 3 /// </summary> 4 /// <param name="sender"></param> 5 /// <param name="e"></param> 6 private void toolStripMenuItem_NewPmd_Click(object sender, EventArgs e) 7 { 8 NewPmd(); 9 } 10 /// <summary> 11 /// 打開pmd文件 12 /// </summary> 13 /// <param name="sender"></param> 14 /// <param name="e"></param> 15 private void toolStripMenuItem_OpenPmd_Click(object sender, EventArgs e) 16 { 17 OpenPmd(); 18 } 19 20 /// <summary> 21 /// 新建Pmd文件 22 /// </summary> 23 private void NewPmd() 24 { 25 IMapDocument mapDocument = new MapDocument(); 26 DialogResult resultType = MessageBox.Show("是否保存當前地圖工程", "新建地圖工程", MessageBoxButtons.YesNoCancel); 27 if (resultType == DialogResult.Cancel) 28 { 29 return; 30 } 31 else if (resultType == DialogResult.Yes) 32 { 33 // 獲得保存路徑信息 34 string pmdFilePath = mapDocument.GetDocumentFilename(); 35 if (string.IsNullOrEmpty(pmdFilePath)) 36 { 37 SaveFileDialog saveFileDialog = new SaveFileDialog(); 38 saveFileDialog.Title = "地圖文檔另存為:"; 39 saveFileDialog.Filter = "PMD|*.pmd"; 40 if (saveFileDialog.ShowDialog() != System.Windows.Forms.DialogResult.OK) return; 41 pmdFilePath = saveFileDialog.FileName; 42 if (string.IsNullOrEmpty(pmdFilePath)) return; 43 } 44 if (!pmdFilePath.EndsWith(".pmd")) 45 { 46 pmdFilePath = pmdFilePath + ".pmd"; 47 } 48 mapDocument.SaveAs(pmdFilePath, true, true); 49 } 50 51 IMapDocument newMapDocument = new MapDocument(); 52 newMapDocument.New(""); //新建地圖工程文檔 53 54 // 為PageLayoutControl設置PageLayout 55 IPageLayout newPageLayout = newMapDocument.GetPageLayout(); 56 pageLayoutControl1.PageLayout = newPageLayout; 57 58 // 為MapControl設置Map 59 IMap newMap = (newPageLayout as IActiveView).FocusMap; 60 mapControl1.FocusMap = newMap; 61 62 if (tabControl1.SelectedIndex == 0) 63 { 64 // 刷新 65 ActivateMapControl(); 66 } 67 else if (tabControl1.SelectedIndex == 1) 68 { 69 // 刷新 70 ActivatePageLayoutControl(); 71 } 72 } 73 /// <summary> 74 /// 打開Pmd文件 75 /// </summary> 76 private void OpenPmd() 77 { 78 OpenFileDialog openFileDialog = new OpenFileDialog(); 79 openFileDialog.Title = "請選擇要打開的地圖文檔:"; 80 openFileDialog.Multiselect = false; 81 openFileDialog.Filter = "PMD|*.pmd"; 82 if (openFileDialog.ShowDialog() != System.Windows.Forms.DialogResult.OK) return; 83 84 string pmdNewFilePath = openFileDialog.FileName; 85 if (string.IsNullOrEmpty(pmdNewFilePath)) return; 86 87 IMapDocument newMapDocument = new MapDocument(); 88 newMapDocument.Open(pmdNewFilePath); 89 90 // 為PageLayoutControl設置PageLayout 91 IPageLayout newPageLayout = newMapDocument.GetPageLayout(); 92 pageLayoutControl1.PageLayout = newPageLayout; 93 94 // 為MapControl設置Map 95 IMap newMap = (newPageLayout as IActiveView).FocusMap; 96 mapControl1.FocusMap = newMap; 97 98 if (tabControl1.SelectedIndex == 0) 99 { 100 ActivateMapControl(); 101 } 102 else if (tabControl1.SelectedIndex == 1) 103 { 104 ActivatePageLayoutControl(); 105 } 106 }
2.3.2 矢量柵格數據的加載
在界面找到自己設計加載數據的按鈕,雙擊按鈕進入代碼界面進行功能開發
1 /// <summary> 2 /// 加載數據 3 /// </summary> 4 /// <param name="sender"></param> 5 /// <param name="e"></param> 6 private void toolStripButton_AddData_Click(object sender, EventArgs e) 7 { 8 //獲取數據路徑 9 OpenFileDialog openFileDialog = new OpenFileDialog(); 10 openFileDialog.Title = "加載數據"; 11 openFileDialog.Multiselect = false; 12 openFileDialog.Filter = "Shape Files|*.shp;*.000|Raster Files|*.tif;*.tiff;*.dat;*.bmp;*.img;*.jpg|HDF Files|*.hdf;*.h5|NC Files|*.nc"; 13 if (openFileDialog.ShowDialog() != System.Windows.Forms.DialogResult.OK) return; 14 15 //加載數據 16 ILayer layer = LayerFactory.CreateDefaultLayer(openFileDialog.FileName); 17 mapControl1.FocusMap.AddLayer(layer); 18 mapControl1.ActiveView.PartialRefresh(ViewDrawPhaseType.ViewAll); 19 }
2.3.3 圖層樹的右鍵操作
圖層樹的右鍵操作在PIESat博客的PIE SDK圖層樹右鍵菜單與命令綁定中有具體的介紹,右鍵菜單主要就是通過右鍵點擊圖層樹彈出ContextMenuStrip控件,在此基礎上進行對圖層的相應操作。
從工具箱中添加ContextMenuStrip控件,Name設置為contextMenuStrip_Layer;
再添加兩個子菜單刪除圖層和縮放至圖層
圖17.右鍵菜單目錄
1 /// <summary> 2 /// toc點擊事件 3 /// </summary> 4 /// <param name="sender"></param> 5 /// <param name="e"></param> 6 private void tocControlMain_MouseClick(object sender, MouseEventArgs e) 7 { 8 if (e.Button == MouseButtons.Right)//右鍵 9 { 10 PIETOCNodeType type = PIETOCNodeType.Null; 11 IMap map = null; 12 ILayer layer = null; 13 Object unk = Type.Missing; 14 Object data = Type.Missing; 15 tocControlMain.HitTest(e.X, e.Y, ref type, ref map, ref layer, ref unk, ref data); 16 17 PIETOCNodeTag tag = new PIETOCNodeTag(); 18 tag.Map = map; 19 tag.Layer = layer; 20 tag.UNK = unk; 21 tag.Data = data; 22 mapControl1.CustomerProperty = tag; 23 24 switch (type) 25 { 26 case PIETOCNodeType.FeatureLayer://矢量 27 IFeatureLayer featureLayer = layer as IFeatureLayer; 28 if (featureLayer == null) return; 29 contextMenuStrip_Layer.Show(tocControlMain, new System.Drawing.Point(e.X, e.Y));//顯示右鍵菜單 30 break; 31 case PIETOCNodeType.RasterLayer://柵格 32 IRasterLayer rasterLayer = layer as IRasterLayer; 33 if (rasterLayer == null) return; 34 contextMenuStrip_Layer.Show(tocControlMain, new System.Drawing.Point(e.X, e.Y)); 35 break; 36 case PIETOCNodeType.Map://地圖 37 contextMenuStrip_TocMenu.Show(tocControlMain, new System.Drawing.Point(e.X, e.Y)); 38 break; 39 } 40 } 41 } 42 43 /// <summary> 44 /// Toc具體選右鍵菜單中具體項的功能操作 45 /// </summary> 46 /// <param name="sender"></param> 47 /// <param name="e"></param> 48 private void tocMenuItem_Click(object sender, MouseEventArgs e) 49 { 50 if (e.Button == MouseButtons.Right) return; 51 ToolStripMenuItem item = sender as ToolStripMenuItem; 52 if (item == null) return; 53 ICommand cmd = item.Tag as ICommand; 54 if (cmd == null) return; 55 56 cmd.OnCreate(mapControl1);//必須加上 57 cmd.OnClick(); 58 59 ITool tool = cmd as ITool; 60 if (tool != null) 61 { 62 mapControl1.CurrentTool = tool; 63 } 64 }
圖18.初始化函數圖
刪除圖層和縮放圖層的MouseUp事件都設置為tocMenuItem_Click事件,在地圖初始化InitFrm()中只需要將圖層右鍵菜單的每一項功能的屬性tag都設置對應的命令,剩下的操作都共用一份代碼,達到了高效便捷的目的;
這種寫法雖然高效但是比較難懂,只是為了更有效高級的開發,翻譯一下上面的寫法就是如下寫法,如果右鍵菜單只是幾個功能可以照下方的方式寫,但是如果是很多功能點會造成代碼的堆砌,最好的方法就是上述示例中的包裝方法
圖19.調用刪除圖層命令
代碼示例中的右鍵菜單的具體功能的實現與博客中的圖層樹的右鍵菜單功能示例中的兩種實現方式都不同,但又有聯系,直接的按鈕事件可以自己根據需求進行功能開發,也可以直接調用現成的命令,如圖15中的刪除圖層,也可以將命令封裝
2.3.4 按鈕命令的綁定
圖20.界面菜單圖
圖16中的程序菜單中的大部分的功能都是直接調用的PIE SDK中已經封裝好的Command,稍后會以列表的方式匯總展示,下面以部分功能進行介紹其用法圖16應用程序菜單
調用命令,需要區分ICommand和ITool的作用,具體介紹請前往PIE SDK Command、Tool、Control的調用和拓展;這篇文章也介紹了Command和Tool的拓展, 即自定義開發功能。
1 //ITool用法 2 3 /// <summary> 4 /// 地圖拉框放大 5 /// </summary> 6 /// <param name="sender"></param> 7 /// <param name="e"></param> 8 private void toolStripButton_MapZoomIn_Click(object sender, EventArgs e) 9 { 10 ITool tool = new MapZoomInTool(); 11 if (tabControl1.SelectedIndex == 0) 12 { 13 (tool as ICommand).OnCreate(mapControl1); 14 mapControl1.CurrentTool = tool; 15 } 16 else if (tabControl1.SelectedIndex == 1) 17 { 18 (tool as ICommand).OnCreate(pageLayoutControl1); 19 pageLayoutControl1.CurrentTool = tool; 20 } 21 } 22 /// <summary> 23 /// 屬性查詢 24 /// </summary> 25 /// <param name="sender"></param> 26 /// <param name="e"></param> 27 private void toolStripButton_AttributeIdentify_Click(object sender, EventArgs e) 28 { 29 ITool attIdentifyTool = new AttributeIdentifyTool(); 30 ICommand cmd = attIdentifyTool as ICommand; 31 if (tabControl1.SelectedIndex == 0) 32 { 33 cmd.OnCreate(mapControl1); 34 cmd.OnClick(); 35 mapControl1.CurrentTool = attIdentifyTool; 36 } 37 }
1 //ICommand 2 3 /// <summary> 4 /// 全圖顯示 5 /// </summary> 6 /// <param name="sender"></param> 7 /// <param name="e"></param> 8 private void toolStripButton_MapFullExtent_Click(object sender, EventArgs e) 9 { 10 ICommand cmd = new FullExtentCommand(); 11 if (tabControl1.SelectedIndex==0) 12 { 13 cmd.OnCreate(mapControl1); 14 } 15 else if(tabControl1.SelectedIndex==1) 16 { 17 cmd.OnCreate(pageLayoutControl1); 18 } 19 cmd.OnClick(); 20 } 21 22 /// <summary> 23 /// 比例尺(制圖) 24 /// </summary> 25 /// <param name="sender"></param> 26 /// <param name="e"></param> 27 private void toolStripMenuItem_DrawScaleBarElement_Click(object sender, EventArgs e) 28 { 29 ICommand cmd = new AddPageScaleBarCommand(); 30 cmd.OnCreate(pageLayoutControl1); 31 cmd.OnClick(); 32 }
2.3.5. 狀態欄的功能實現
狀態欄中的信息有坐標系信息,比例尺,地圖坐標和屏幕坐標,這些主要在MapControl和PageLayoutControl控件上操作,可以前往PIE SDK地圖鼠標事件監聽進行查看。
1 /// <summary> 2 /// 鼠標在MapControl上移動 3 /// </summary> 4 /// <param name="sender"></param> 5 /// <param name="e"></param> 6 private void mapControl1_MouseMove(object sender, MouseEventArgs e) 7 { 8 //1、當地圖空間參考為空時,鼠標移動不起作用 9 int layerCount = mapControl1.FocusMap.GetAllLayer().Count; 10 if (layerCount < 1) 11 { 12 mapControl1.SpatialReference = null; 13 } 14 ISpatialReference spatialReference = mapControl1.SpatialReference; 15 if (spatialReference == null) 16 { 17 toolStripStatusLabel_CoordinateInfo.Text = null; 18 return; 19 } 20 21 toolStripStatusLabel_CoordinateInfo.Text = spatialReference.Name.ToString(); 22 //2、鼠標移動的屏幕坐標 23 toolStripStatusLabel_screenCoordinate.Text = string.Format("{0},{1}", e.X, e.Y); 24 //3、鼠標移動的地圖坐標 25 IPoint point = mapControl1.ToMapPoint(e.X, e.Y); 26 toolStripStatusLabel_coordinateSystem.Text = string.Format("{0},{1}", point.X.ToString("0.0000"), point.Y.ToString("0.0000"));//保留四位小數 27 }
比例尺調用的PIE SDK 封裝的控件,具體的比例尺看PIE SDK地圖范圍設置博客中的即可,主要是對mapControl1.ActiveView.DisplayTransformation.MapScale的設置。
圖21
3. 代碼路徑
項目路徑 |
百度雲盤地址下/PIE示例程序/15.綜合運用/PIEApplication1 |
視頻路徑 |
百度雲盤地址下/PIE視頻教程/15.綜合運用/組件式開發綜合運用示例.avi |