1、桌面 GIS 系统开发报告组员:钱堂慧,王淼,娄静谊李勇发,骆延青前言本系统是基于ArcGIS Engine的二次开发,以 Visual Studio 2010 作为开发环境,C#为开发语言,.NET 为组件技术;支持个人地理数据库(.mdb)、文件地理数据库(.gdb) 对空间数据进 行管理;能完成基本的矢量化工作。主要的功能模块包括:各种空间数据的加载显示、图层管理;图形数据与属性数据的互查;图层符号选择;个人地理数据库、文件地理数据库和 Shapefile 文件的创建;图形数据和属性数据的编辑、保存等。一 开发工具简介和系统功能设计1.1 ArcGIS Engine介绍 ArcGIS E
2、ngine是一个简单的、独立于应用程序的 Arc Objects 编程环境,开发人员用于建立自定义应用程序的嵌入式 GIS 组件的一个完整类库。Arc Engine由一个软件开发包和一个可以重新分发的为 ArcGIS 应用程序提供平台的运行时(runtim e)组成。ArcGIS Engine 功能层次:(1)基本服务:由 GIS 核心Arc Objects 构成,如要素几何体和显示。(2)数据存储: ArcGIS Engine 可以对许多栅格和矢量格式进行存取,包括强大而灵活的地理数据库。(3)地图表达:包括用于创建和显示带有符号体系和标注功能的地图的Arc ,以及包括创建 自定义应用程 序
3、的专题图功能的 Arc Objects。(4)开发组件:用于快速应用程序开发的高级用户接口控件和高效开发的一个综合帮助系统。(5)运行时选项:Arc Engine 运行时可以与标准功能或其他高级功能一起部署。ArcGIS Engine类库:System类库:是 Engine 中最底层的类库。包含给构成 ArcGIS 的其他类库提供服务的组件。库中包含了大量可供开发者调用的接口。SystemUI 类库:主要定义了 ArcGIS 系统中所使用的用户界面组件类型。Geometry 类库:包含了核心几何对象,如点、线、多边形及其几何类型和定义。Display 类库:包含了支持向输出装置绘制符号体系的组
4、件,1.2 .NET FrameWork 简介C#语言编写的程序需要在.NET Framework 环境的支持下才可以运行,微软在其不断升级的 Windows 操作系统中逐渐嵌入了更高级版本的.NET Framework(如 win7 内嵌入了.NET Framework 3.5) 。C#语言是微软公司专门为.NET Framework 框架量身打造的首选编程语言。 C#就本身而言只是一种语言,尽管它是用于生成面向.NET 环境的代码,但它本身不是.NET 的一部分。另外,.NET 支持的一些特性,C#并不支持,而 C#语言支持的另一些特性,.NET 也不支持(如运算符重载) 。在安装 Vis
5、ual Studio开发平台的同时,.NET Framework框架也被安装到本地计算机中。.NET Framework 是支持生成、运行下一代应用程序和 XML Web Services 的内部 Windows组件,它简化了在高度分布式 internet环境中的应用程序开发。.NET Framework 旨在实现以下目标:(1)提供一个完善的面向对象编程环境,无论代码是在本地存储执行,还是在 Internet 上分布,或者是在远程执行的。(2)提供一个良好的代码执行环境,使开发人员的经验在面对类型大不相同的应用程序(如基于 Web的应用程序)时保持一致。(3)按照工业标准生成所有通信,以确保
6、基于.NET Framework 的代码可以与任何其他代码集成。.NET Framework 包括公共语言运行库(简称 CLR) 、.NET Framework 类库和NET 程序编译原理 3 个核心概念。下图 3-2 为.NET Framework 框架下程序编译过程:C#代码 VB.NET代码VC+.NET代码编译器 编译器 编译器组织结构公共语言中间语言公共语言运行库机器语言01001100101011图 3-2 .NET 程序编译过程1.3 基于.NET 的 ArcGIS Engine开发平台构建安装 Visual Studio 2010 和 ArcGIS Engine 10.0,其中
7、 ArcGIS Engine Developer Kit 必须安装 ArcGIS License Manager 和 ArcGIS Engine Developer Kit for Windows的 ArcGIS Engine Runtime for Windows 和 ArcObjects SDK for the Microsoft .NET Framework。如果想在程序中直接调用 ArcMap 中的符号选择器 ,必须安装ArcGIS Desktop。安装完成后,打开 Visual Studio 2010 编程环境,进行初始配置。选择 C#作为默认编程语言,把应用程序用到的 ArcGIS
8、 控件和其 它的 ArcGIS Engine库引用装载到开发环境之中。在工具箱窗的任意地方处点击右键,在弹出的菜单中点击“添加选项卡(A) ”,可命名为“ArcGIS Windows Forms”,然后再在新添加的选项卡下面点击右键,在弹出的菜单中点击“选择项(I)” ,弹出对话框“选择工具箱” ,在.NET Framework 组件下选择 ESRI 提供的控件。如图 1.1所示:图 1.1 选择工具箱选项1.4 系统功能设计系统的功能目标是能完成基本的矢量化工作,这就要求实现各种空间数据的加载显示;图层控制和属性数据查看;图层符号选择;地理数据库和Shapefile 文件的创建、数据导入导出
9、;地理数据的编辑、保存等功能。功能结构如图1.2。空间地理数据库(GeoDtabase )桌面 GIS 系统空间数据加载显示图层控制和属性查看图层符号选择器空间数据管理新建数据库新建要素类导入要素类空间数据编辑保存查看空间数据信息图 1.2 系统功能结构图二 系统功能实现2.1 桌面 GIS系统框架主要是使用SplitContainer、TabControl、MapControl、PageLayoutControl、ToolbarControl、TOCControl、MenuStrip、StatusStrip 等控件建立起基本的桌面 GIS 应用程序框架。最终成果预览如下:图 2.1 桌面 G
10、IS系统框架(1)添加控件选择工具箱中的“容器|SplitContainer”容器拖入窗体,为splitContainer1,将其属性中的Dock 设置为 Fill,Orientation 设为Horizontal,FixedPanel 设为Panel1。选择工具箱中的“菜单和工具栏”MenuStrip” ,将其拖入splitContainer1 的 Panel1。再选择 “ArcGIS Windows Forms”, 拖入两个“ToolbarControl”和一个“菜单和工具栏|ToolStrip”控件到splitContainer1的 Panel1。向 splitContainer1 的
11、Panel2 再拖入一个SplitContainer,为 splitContainer2,将其属性中的Dock 设置为Fill,Orientation 设为 Vertical。向 splitContainer2 的 Panel1 再拖入一个 SplitContainer ,为 splitContainer3,将其属性中的Dock 设置为Fill,Orientation 设为 Horizontal。将 TabControl 控件拖入 splitContainer3的 Panel1,将 Alignment 属性设置为 Bottom,Dock 属性设置为 Fill。点击 TabPages 属性右边的
12、按钮,弹出TabPage 集合编辑器,将 tabPage1 的 Name 设置为 tabPageLayer,Text 设置为图层,将 tabPage2 的 Name 设置为 tabPageProperty,Text 设置为属性。选择“图层”选项卡,拖入 TOCControl控件,设置 Dock属性为 Fill。选择“属性”选项卡,拖入 PropertyGrid 控件,设置 Dock属性为 Fill。如下所示:图 2.2 tabPage 集合编辑器拖入“菜单和工具栏|StatusStrip”和 TabControl 控件到splitContainer2 的Panel2,设置 TabControl
13、的 Dock 属性为 Fill。并以上述类似的方法,将两个选项卡的 Name 和Text 分别设置为:(tabPageMap、地图)(tabPageLayout,制版) 。选择“地图”选项卡,拖入 MapControl控件(用于主地图的显示) ,设置 Dock属性为 Fill。选择“制版”选项卡,拖入PageLayoutControl 控件,设置 Dock属性为 Fill。最后再拖入一个 MapControl 控件到 splitContainer3 的Panel2(用于鹰眼功能) ,并将 LicenseControl 控件拖入到窗体的任意地方。(2)控件绑定通过以上步骤添加的控件还只是单独存在
14、,而我们的程序需要各控件间协同工作,因此要进行控件绑定。分别右击 ToolbarControl、TOCControl 控件,将 Buddy设置为 axMapControl1,如下图所示。图 2.3(3)添加工具此时,工具条中还没有任何工具,添加的方法是右击 ToolbarControl,选择“属性|Items”,点击 Add,选择 Commands 选项卡中的 Generic,双击工具图标即可将相应工具添加到工具条。分别为 axToolbarControl1 和 axToolbarControl2选择不同的工具。图 2.4这样就基本完成了系统框架的建立。最终布局结果如图 2.5:图 2.5 2
15、.2 菜单栏(menuStrip1)和工具栏(toolStrip1)的添加与实现(1)添加菜单和工具在设计视图中,单击菜单栏,会出现“请在此处键入” 的提示,单击提示就可以键入菜单名称,如“ 文件 ”,再单击“文件”,即可输入其下 拉子菜单。添加新建( New )、打开( Open )、保存( Save )、另存为( SaveAs )、退出( Exit )这些菜单,()内为相应的Name 属性值。可以在属性面板中的Text 属性中,把菜单名设置为中英文形式 ,如“打开O pen ”,带下划线的O 表示此项菜单的快捷键是字母O ,设置方法是在 相应字母前加上“ using System.Coll
16、ections;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.IO;using ESRI.ArcGIS.esriSystem; using ESRI.ArcGIS.SystemUI;using ESRI.ArcGIS.Carto;using ESRI.ArcGIS.Controls;using
17、 ESRI.ArcGIS.Display;using ESRI.ArcGIS.DisplayUI;using ESRI.ArcGIS.Geometry;using ESRI.ArcGIS.Geodatabase;using ESRI.ArcGIS.GeoDatabaseUI;using ESRI.ArcGIS.GeoDatabaseExtensions;using ESRI.ArcGIS.DataSourcesFile;using ESRI.ArcGIS.DataSourcesRaster;using ESRI.ArcGIS.DataSourcesGDB;using ESRI.ArcGIS.E
18、ditingTools;using ESRI.ArcGIS.Editor;using ESRI.ArcGIS.ServerTools;using ESRI.ArcGIS.ArcMap;1)菜单(文件(F ile) )/新建空白地图文档private void New_Click(object sender, EventArgs e)NewMapDocumentFrm newMapDocumentFrm = new NewMapDocumentFrm();if (newMapDocumentFrm.ShowDialog()=DialogResult.OK)if (newMapDocumentFr
19、m.SavePath = null) return;string path = newMapDocumentFrm.SavePath + “untitled.mxd“;MessageBox.Show(path);MapDocument pMapDocument = new MapDocumentClass();pMapDocument.New(path);pMapDocument.Open(path, “);axMapControl1.Map = pMapDocument.get_Map(0);/newMapDocumentFrm 是选择保存路径的对话框,如下图:图 2.8/获取路径的代码st
20、ring savePath;public string SavePathget return savePath; set savePath = value; private void btDir_Click(object sender, EventArgs e)if (this.folderBrowserDialog1.ShowDialog()=DialogResult.OK)savePath = folderBrowserDialog1.SelectedPath;tbPath.Text = savePath;private void btOK_Click(object sender, Eve
21、ntArgs e)this.Close();this.Dispose();private void btCancel_Click(object sender, EventArgs e)this.Close();this.Dispose();/打开地图文档(.mxd)private void Open_Click(object sender, EventArgs e)ICommand command = new ControlsOpenDocCommand();command.OnCreate(axMapControl1.Object);command.OnClick();/保存地图文档(.mx
22、d)private void Save_Click(object sender, EventArgs e)if (axMapControl1.DocumentFilename != null pMapDocument.Open(axMapControl1.DocumentFilename, “);IMxdContents mxdContents = axMapControl1.ActiveView.FocusMap as IMxdContents;pMapDocument.ReplaceContents(mxdContents);pMapDocument.Save(true, false);M
23、essageBox.Show(“保存成功“);pMapDocument.Close();elseMessageBox.Show(“无效地图文档“);/另存为private void SaveAs_Click(object sender, EventArgs e)ICommand pCommand = new ControlsSaveAsDocCommand();pCommand.OnCreate(this.axMapControl1.Object);pCommand.OnClick();/退出private void Exit_Click(object sender, EventArgs e)
24、System.Windows.Forms.Application.Exit();2)工具栏(toolSt rip1)/打开地图文档(.mxd)private void btOpenDoc_Click(object sender, EventArgs e)ICommand command = new ControlsOpenDocCommand();command.OnCreate(axMapControl1.Object);command.OnClick();/保存地图文档private void btSaveDoc_Click(object sender, EventArgs e)IComm
25、and command = new ControlsSaveAsDocCommand();command.OnCreate(axMapControl1.Object);command.OnClick();/添加各种空间数据private void btAddData_ButtonClick(object sender, EventArgs e)AddDataDialogFrm addDataDialogFrm = new AddDataDialogFrm();addDataDialogFrm.ShowDialog();currentLayerList=addDataDialogFrm.Curr
26、entLayerList;if (currentLayerList = null) return;for (int i=0; i 0)m_path = pPath.Substring(findex + 1);elsem_path = pPath;int index = m_path.LastIndexOf(.);if (index 0)listItem.ImageIndex = 14;listView1.Items.Add(listItem);/遍历文件for (int i = 0; i files.Length; i+)string filePath = System.IO.Path.Get
27、DirectoryName(filesi);string fileName = System.IO.Path.GetFileName(filesi);string filter = fileName.Substring(fileName.IndexOf(.) + 1, fileName.Length - fileName.IndexOf(.) - 1);if (filter = “shp“)try IWorkspaceFactory pWorkspaceFactory = new ShapefileWorkspaceFactoryClass();IWorkspace pWorkspace=pW
28、orkspaceFactory.OpenFromFile(filePath, 0);IFeatureWorkspace pFeatureWorkspace = (IFeatureWorkspace)pWorkspaceFactory.OpenFromFile(filePath, 0);IFeatureLayer pFeatureLayer = new FeatureLayerClass();pFeatureLayer.FeatureClass = pFeatureWorkspace.OpenFeatureClass(fileName);listItem = new ListViewItem()
29、;listItem.Text = fileName;if (pFeatureLayer.FeatureClass.ShapeType = esriGeometryType.esriGeometryPoint)listItem.ImageIndex = 8;if (pFeatureLayer.FeatureClass.ShapeType = esriGeometryType.esriGeometryLine)listItem.ImageIndex = 7;if (pFeatureLayer.FeatureClass.ShapeType = esriGeometryType.esriGeometr
30、yPolyline)listItem.ImageIndex = 7;if (pFeatureLayer.FeatureClass.ShapeType = esriGeometryType.esriGeometryPolygon)listItem.ImageIndex = 9;listView1.Items.Add(listItem);catch (System.Exception ex)listView1.Items.Clear();if (filter = “mdb“)listItem = new ListViewItem();listItem.Text = fileName;listIte
31、m.ImageIndex = 3;listView1.Items.Add(listItem);if (filter = “dwg“)listItem = new ListViewItem();listItem.Text = fileName;listItem.ImageIndex = 17;listView1.Items.Add(listItem);if (filter = “jpg“)listItem = new ListViewItem();listItem.Text = fileName;listItem.ImageIndex = 13;listView1.Items.Add(listI
32、tem);if (filter = “gif“)listItem = new ListViewItem();listItem.Text = fileName;listItem.ImageIndex = 13;listView1.Items.Add(listItem);if (filter = “tiff“)listItem = new ListViewItem();listItem.Text = fileName;listItem.ImageIndex = 13;listView1.Items.Add(listItem);if (filter = “bmp“)listItem = new Li
33、stViewItem();listItem.Text = fileName;listItem.ImageIndex = 13;listView1.Items.Add(listItem);/listView1显示文件夹、mdb数据库、gdb数据库下面的shapefile数据和栅格数据集public void listViewItemDataFiles(string pFilePath,string pFileName,int pImageIndex)this.listView1.Items.Clear();string filter = pFilePath.Substring(pFilePath
34、.LastIndexOf(.) + 1);GetGeoData getGeoData = new GetGeoData();if (filter = “mdb“)getGeoData.AddMDBDataFileToListView(listView1, pFilePath, pFileName);if (filter = “gdb“)getGeoData.AddGDBDataFileToListView(listView1, pFilePath, pFileName);if (pImageIndex=13)getGeoData.AddRasterBandFileToListView(list
35、View1, pFilePath, null);if (filter = “dwg“)pFilePath = pFilePath.Substring(0, pFilePath.LastIndexOf(“);getGeoData.AddCADDataFileToListView(this.listView1, pFilePath, pFileName);int pImageIndex;ArrayList filesNameList;public ArrayList FilesNameListget return filesNameList; set filesNameList = value;
36、private void listView1_MouseClick(object sender, MouseEventArgs e)ListViewHitTestInfo info = listView1.HitTest(e.X, e.Y);if (info.Item != null)if (e.Button = MouseButtons.Left)tbFileName.Text = null;listView1.MultiSelect = true;int pItemsCount = listView1.SelectedItems.Count;if (pItemsCount1) return
37、;filesNameList = new ArrayList();for (int i = 0; i pItemsCount; i+)filesNameList.Add(listView1.SelectedItemsi.Text);tbFileName.Text = filesNameList0 as string;for (int j = 1; j filesNameList.Count; j+)tbFileName.Text = tbFileName.Text + ; + filesNameListj;/cbSearchRange.Text = cbSearchRange.Text +“+
38、 info.Item.Text;pImageIndex = info.Item.ImageIndex;ILayer currentLayer;public ILayer CurrentLayerget return currentLayer; set currentLayer = value; private void listView1_MouseDoubleClick(object sender, MouseEventArgs e)ListViewHitTestInfo info = listView1.HitTest(e.X, e.Y);if (info.Item != null)Get
39、GeoData getGeoData = new GetGeoData();currentLayerList = new ArrayList();/如果是可支持的地理数据,添加到axMapControlsif (pImageIndex = 7 | pImageIndex = 8 | pImageIndex = 9 | pImageIndex = 16 | pImageIndex = 18 | pImageIndex = 19 | pImageIndex = 20 | pImageIndex = 21 | pImageIndex = 22)string pFilePath = m_path;st
40、ring pFileName = tbFileName.Text; /添加shapefile数据(点、线、面要素类)if (pImageIndex = 7 | pImageIndex = 8 | pImageIndex = 9)int pIndex = pFilePath.IndexOf(.);/如果数据来源于文件夹if (pIndex 0)getGeoData.AddShpefileData(pFilePath, pFileName);currentLayer = getGeoData.CurrentLayer;currentLayerList.Add(currentLayer);elses
41、tring filter = pFilePath.Substring(pIndex + 1);/如果数据来源于个人地理数据库(*.mdb)if (filter = “mdb“)getGeoData.AddMDBData(pFilePath, pFileName);currentLayer = getGeoData.CurrentLayer;currentLayerList.Add(currentLayer);/如果数据来源于文件地理数据库(*.gdb)if (filter = “gdb“)getGeoData.AddGDBData(pFilePath, pFileName);currentLa
42、yer = getGeoData.CurrentLayer;currentLayerList.Add(currentLayer);/如果是栅格数据if (pImageIndex = 16)for (int i = 0; i filesNameList.Count; i+)pFileName = filesNameListi as string;MessageBox.Show(pFilePath + “ + pFileName);getGeoData.AddRasterBandData(pFilePath, pFileName);currentLayer = getGeoData.Current
43、Layer;CurrentLayerList.Add(currentLayer);/如果是CAD数据if (pImageIndex = 18 | pImageIndex = 19 | pImageIndex = 20 | pImageIndex = 21 | pImageIndex = 22)string CADFilePath = pFilePath.Substring(0, pFilePath.LastIndexOf(“);string CADFileName = pFilePath.Substring(pFilePath.LastIndexOf(“) + 1);getGeoData.Ad
44、dCADFileData(CADFilePath, CADFileName, pImageIndex);currentLayerList = getGeoData.CurrentLayerList;SystemDatabaseManage systemDatabaseManage = new SystemDatabaseManage();systemDatabaseManage.Insert(pFilePath, pFileName, null, null);this.Close();this.Dispose();else/如果是文件夹或数据库,添加到ListViewthis.listView
45、1.Items.Clear();subpath = tbFileName.Text.Trim();if (subpath = null) return;m_path = m_path + “ + subpath;int index = m_path.IndexOf(.);if (index 0)listViewItemDirectories(m_path);elselistViewItemDataFiles(m_path, subpath, pImageIndex);cbSearchRange.Text = cbSearchRange.Text + “ + info.Item.Text;Arr
46、ayList currentLayerList;public ArrayList CurrentLayerListget return currentLayerList; set currentLayerList = value; private void btAdd_Click(object sender, EventArgs e) if (pImageIndex = 7 | pImageIndex = 8 | pImageIndex = 9 | pImageIndex = 13 | pImageIndex = 16 | pImageIndex = 17 | pImageIndex = 18
47、 | pImageIndex = 19 | pImageIndex = 20 | pImageIndex = 21 | pImageIndex = 22)string pFilePath = m_path;string pFileName = tbFileName.Text.Trim();currentLayerList = new ArrayList();GetGeoData getGeoData = new GetGeoData();/添加shapefile数据(点、线、面要素类)if (pImageIndex = 7 | pImageIndex = 8 | pImageIndex = 9
48、)int pIndex = pFilePath.IndexOf(.);/如果数据来源于文件夹if (pIndex 0)for (int i = 0; i filesNameList.Count;i+ )pFileName=filesNameListi as string;getGeoData.AddShpefileData(pFilePath, pFileName);currentLayer = getGeoData.CurrentLayer;CurrentLayerList.Add(currentLayer); elsestring filter = pFilePath.Substring(pIndex + 1);/如果数据来源于个人地理数据库(*.mdb)if (filter = “mdb“)for (int i = 0; i filesNameList.Count; i+)pFileName = filesNameListi as string;getGeoData.AddMDBData(pFilePath, pFileName);currentLayer = getGeoData.CurrentLayer;CurrentLayerList.Add(currentLay