PIE SDK组件式开发综合运用示例
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 |