《ArcGIS Engine+C#实例开发教程》第七讲 图层符号选择器的实现

原文:《ArcGIS Engine+C#实例开发教程》第七讲 图层符号选择器的实现

摘要:我们要实现的是图层符号选择器,与ArcMap中的Symbol Selector的类似。本讲较前几讲而言,些许有些复杂,不过只要仔细琢磨,认真操作,你就很容易实现如下所示的符号选择器。 

教程目录:

第一讲 桌面GIS应用程序框架的建立

第二讲 菜单的添加及其实现

第三讲 MapControl与PageLayoutControl同步

第四讲 状态栏信息的添加与实现

第五讲 鹰眼的实现

第六讲 右键菜单添加与实现

教程Bug及优化方案1

第七讲 图层符号选择器的实现1

第七讲 图层符号选择器的实现2

第八讲 属性数据表的查询显示

------------------------------------------------------------------

在上一讲中,我们实现了右键菜单(ContextMenu)的添加与实现,在最后我预留给下一讲的问题是TOCControl控件图层拖拽的实现。后来发现此功能的实现异常简单,只要在TOCControl的属性页中,勾选“Enable Layer Drag and Drop”即可。

这一讲,我们要实现的是图层符号选择器,与ArcMap中的Symbol Selector的类似。本讲较前几讲而言,些许有些复杂,不过只要仔细琢磨,认真操作,你就很容易实现如下所示的符号选择器。因为本讲篇幅较长,故我将其分成两个阶段,本文是第一阶段。

图1

在AE开发中,符号选择器有两种实现方式。

一是在程序中直接调用ArcMap中的符号选择器,如下所示:

图2

二是自定义符号选择器,如图1所示。

由于第一种方式前提是必须安装ArcGIS Desktop,其界面还是英文的,而对二次开发来说,大部分用户希望应该是中文界面。因此开发人员通常选择第二种方式,本讲也着重讲解第二种方式。

通过对《ArcGIS Engine+C#实例开发教程》前六讲的学习,我已经假定你已经基本熟悉C#语言和VS2005的操作,故在下面的教程中,我不准备说明每一步骤的具体操作方法,而只是说明操作步骤,以节省时间和篇幅。


1.        直接调用ArcMap中的符号选择器

(1)添加ESRI.ArcGIS.DisplayUI的引用。

分别在解决方案管理器和代码中添加引用。

(2)添加TOCControl的Double_Click事件。

(3)实现TOCControl的Double_Click事件。

因为种方法不是本讲的重点,故不对代码进行分析,有兴趣的读者请自行理解或结合后面的内容理解。代码如下:

 private void axTOCControl1_OnDoubleClick(object sender, ITOCControlEvents_OnDoubleClickEvent e)

{

esriTOCControlItem toccItem = esriTOCControlItem.esriTOCControlItemNone;

ILayer iLayer = null;

IBasicMap iBasicMap = null;

object unk = null;

object data = null;

if (e.button == 1)

{

axTOCControl1.HitTest(e.x, e.y, ref toccItem, ref iBasicMap, ref iLayer, ref unk,

ref data);

System.Drawing.Point pos = new System.Drawing.Point(e.x, e.y);

if (toccItem == esriTOCControlItem.esriTOCControlItemLegendClass)

{

ESRI.ArcGIS.Carto.ILegendClass pLC = new LegendClassClass();

ESRI.ArcGIS.Carto.ILegendGroup pLG = new LegendGroupClass();

if (unk is ILegendGroup)

{

pLG = (ILegendGroup)unk;

}

pLC = pLG.get_Class((int)data);

ISymbol pSym;

pSym = pLC.Symbol;

ESRI.ArcGIS.DisplayUI.ISymbolSelector pSS = new

ESRI.ArcGIS.DisplayUI.SymbolSelectorClass();

bool bOK = false;

pSS.AddSymbol(pSym);

bOK = pSS.SelectSymbol(0);

if (bOK)

{

pLC.Symbol = pSS.GetSymbolAt(0);

}

this.axMapControl1.ActiveView.Refresh();

this.axTOCControl1.Refresh();

}

}

}

(4)编译运行即可。

2.        自定义符号选择器

AE9.2提供了SymbologyControl控件,极大的方便了图层符号选择器的制作。本讲实现的符号选择器有如下功能。

用户双击TOCControl控件中图层的符号时,弹出选择符号对话框,对话框能够根据图层类型自动加载相应的符号,如点、线、面。用户可以调整符号的颜色、线宽、角度等参数。还可以打开自定义的符号文件(*.ServerStyle),加载更多的符号。

2.1     新建符号选择器窗体

新建Winodws窗体,命名为SymbolSelectorFrm,修改窗体的Text属性为“选择符号”。并添加SymboloryControl、PictureBox、Button、Label、NumericUpDown、GroupBox、ColorDialog、OpenFileDialog、ContextMenuStrip控件。控件布局如下所示:

图3

2.2     设置控件属性

 

设置相应控件的相关属性,如下表所示(空则不用修改):


控件


Name属性


Text属性


其它


SymbologyControl


axSymbologyControl


PictureBox


ptbPreview


Label


lblColor


颜色


Label


lblSize


大小


Label


lblWidth


线宽


Label


lblAngle


角度


Label


lblOutlineColor


外框颜色


NumericUpDown


nudSize


NumericUpDown


nudWidth


NumericUpDown


nudAngle


Button


btnColor


(设置为空)


Button


btnOutlineColor


(设置为空)


Button


btnMoreSymbols


更多符号


Button


btnOK


确定


DialogResult属性设为OK


Button


btnCancel


取消


GroupBox


groupBox1


预览


GroupBox


groupBox2


设置


ColorDialog


colorDialog


OpenFileDialog


openFileDialog


Filter属性设置为:

Styles 文件|*.ServerStyle


ContextMenuStrip


contextMenuStripMoreSymbol

2.3     添加引用

在解决方案资源管理器中添加ArcGIS Engine的ESRI.ArcGIS.Geodatabase引用,在SymbolSelectorFrm.cs文件中添加如下引用代码:

   using ESRI.ArcGIS.Carto;

using ESRI.ArcGIS.Display;

using ESRI.ArcGIS.esriSystem;

using ESRI.ArcGIS.SystemUI;

using ESRI.ArcGIS.Controls;

using ESRI.ArcGIS.Geodatabase;

 

2.4   初始化

(1)       添加SymbolSelectorFrm的全局变量,代码如下:


private IStyleGalleryItem pStyleGalleryItem;

private ILegendClass pLegendClass;

private ILayer pLayer;

public ISymbol pSymbol;

public Image pSymbolImage;

(2)       修改SymbolSelectorFrm的构造函数,传入图层和图例接口。代码如下:

   /// <summary>

/// 构造函数,初始化全局变量

/// </summary>

/// <param name="tempLegendClass">TOC图例</param>

/// <param name="tempLayer">图层</param>

public SymbolSelectorFrm(ILegendClass tempLegendClass, ILayer tempLayer)

{

InitializeComponent();

this.pLegendClass = tempLegendClass;

this.pLayer = tempLayer;

}

(3)       添加SymbolControl的SymbologyStyleClass设置函数SetFeatureClassStyle(),代码如下:


/// <summary>

/// 初始化SymbologyControl的StyleClass,图层如果已有符号,则把符号添加到SymbologyControl中的第一个符号,并选中

/// </summary>

/// <param name="symbologyStyleClass"></param>

private void SetFeatureClassStyle(esriSymbologyStyleClass symbologyStyleClass)

{

this.axSymbologyControl.StyleClass = symbologyStyleClass;

ISymbologyStyleClass pSymbologyStyleClass = this.axSymbologyControl.GetStyleClass(symbologyStyleClass);

if (this.pLegendClass != null)

{

IStyleGalleryItem currentStyleGalleryItem = new ServerStyleGalleryItem();

currentStyleGalleryItem.Name = "当前符号";

currentStyleGalleryItem.Item = pLegendClass.Symbol;

pSymbologyStyleClass.AddItem(currentStyleGalleryItem,0);

this.pStyleGalleryItem = currentStyleGalleryItem;

}

pSymbologyStyleClass.SelectItem(0);

}

(4)       添加注册表读取函数ReadRegistry(),此函数从注册表中读取ArcGIS的安装路径,代码如下:

    /// <summary>

/// 从注册表中取得指定软件的路径

/// </summary>

/// <param name="sKey"></param>

/// <returns></returns>

private string ReadRegistry(string sKey)

{

//Open the subkey for reading

Microsoft.Win32.RegistryKey rk = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(sKey, true);

if (rk == null) return "";

// Get the data from a specified item in the key.

return (string)rk.GetValue("InstallDir");

}

(5)       添加SymbolSelectorFrm的Load事件。根据图层类型为SymbologyControl导入相应的符号样式文件,如点、线、面,并设置控件的可视性。代码如下:


private void SymbolSelectorFrm_Load(object sender, EventArgs e)

{

//取得ArcGIS安装路径

string sInstall = ReadRegistry("SOFTWARE\\ESRI\\CoreRuntime");

//载入ESRI.ServerStyle文件到SymbologyControl

this.axSymbologyControl.LoadStyleFile(sInstall + "\\Styles\\ESRI.ServerStyle");

//确定图层的类型(点线面),设置好SymbologyControl的StyleClass,设置好各控件的可见性(visible)

IGeoFeatureLayer pGeoFeatureLayer = (IGeoFeatureLayer)pLayer;

switch (((IFeatureLayer)pLayer).FeatureClass.ShapeType)

{

case ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPoint:

this.SetFeatureClassStyle(esriSymbologyStyleClass.esriStyleClassMarkerSymbols);

this.lblAngle.Visible = true;

this.nudAngle.Visible = true;

this.lblSize.Visible = true;

this.nudSize.Visible = true;

this.lblWidth.Visible = false;

this.nudWidth.Visible = false;

this.lblOutlineColor.Visible = false;

this.btnOutlineColor.Visible = false;

break;

case ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolyline:

this.SetFeatureClassStyle(esriSymbologyStyleClass.esriStyleClassLineSymbols);

this.lblAngle.Visible = false;

this.nudAngle.Visible = false;

this.lblSize.Visible = false;

this.nudSize.Visible = false;

this.lblWidth.Visible = true;

this.nudWidth.Visible = true;

this.lblOutlineColor.Visible = false;

this.btnOutlineColor.Visible = false;

break;

case ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolygon:

this.SetFeatureClassStyle(esriSymbologyStyleClass.esriStyleClassFillSymbols);

this.lblAngle.Visible = false;

this.nudAngle.Visible = false;

this.lblSize.Visible = false;

this.nudSize.Visible = false;

this.lblWidth.Visible = true;

this.nudWidth.Visible = true;

this.lblOutlineColor.Visible = true;

this.btnOutlineColor.Visible = true;

break;

case ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryMultiPatch:

this.SetFeatureClassStyle(esriSymbologyStyleClass.esriStyleClassFillSymbols);

this.lblAngle.Visible = false;

this.nudAngle.Visible = false;

this.lblSize.Visible = false;

this.nudSize.Visible = false;

this.lblWidth.Visible = true;

this.nudWidth.Visible = true;

this.lblOutlineColor.Visible = true;

this.btnOutlineColor.Visible = true;

break;

default:

this.Close();

break;

}

}

(6)       双击确定按钮和取消按钮,分别添加如下代码:

    /// <summary>

/// 确定按钮

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void btnOK_Click(object sender, EventArgs e)

{

//取得选定的符号

this.pSymbol = (ISymbol)pStyleGalleryItem.Item;

//更新预览图像

this.pSymbolImage = this.ptbPreview.Image;

//关闭窗体

this.Close();

}

/// <summary>

/// 取消按钮

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void btnCancel_Click(object sender, EventArgs e)

{

this.Close();

}

(7)       为了操作上的方便,我们添加SymbologyControl的DoubleClick事件,当双击符号时同按下确定按钮一样,选定符号并关闭符号选择器窗体。代码如下:

    /// <summary>

/// 双击符号同单击确定按钮,关闭符号选择器。

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void axSymbologyControl_OnDoubleClick(object sender, ESRI.ArcGIS.Controls.ISymbologyControlEvents_OnDoubleClickEvent e)

{

this.btnOK.PerformClick();

}

(8)       再添加符号预览函数,当用户选定某一符号时,符号可以显示在PictureBox控件中,方便预览,函数代码如下:


/// <summary>

/// 把选中并设置好的符号在picturebox控件中预览

/// </summary>

private void PreviewImage()

{

stdole.IPictureDisppicture =this.axSymbologyControl.GetStyleClass(this.axSymbologyControl.StyleClass).PreviewItem(pStyleGalleryItem,this.ptbPreview.Width, this.ptbPreview.Height);

System.Drawing.Image image = System.Drawing.Image.FromHbitmap(new System.IntPtr(picture.Handle));

this.ptbPreview.Image = image;

}

(9)       当SymbologyControl的样式改变时,需要重新设置符号参数调整控件的可视性,故要添加SymbologyControl的OnStyleClassChanged事件,事件代码与Load事件类似,如下:

    /// <summary>

/// 当样式(Style)改变时,重新设置符号类型和控件的可视性

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

privatevoid axSymbologyControl_OnStyleClassChanged(object sender,ESRI.ArcGIS.Controls.ISymbologyControlEvents_OnStyleClassChangedEvent e)

{

switch ((esriSymbologyStyleClass)(e.symbologyStyleClass))

{

case esriSymbologyStyleClass.esriStyleClassMarkerSymbols:

this.lblAngle.Visible = true;

this.nudAngle.Visible = true;

this.lblSize.Visible = true;

this.nudSize.Visible = true;

this.lblWidth.Visible = false;

this.nudWidth.Visible = false;

this.lblOutlineColor.Visible = false;

this.btnOutlineColor.Visible = false;

break;

case esriSymbologyStyleClass.esriStyleClassLineSymbols:

this.lblAngle.Visible = false;

this.nudAngle.Visible = false;

this.lblSize.Visible = false;

this.nudSize.Visible = false;

this.lblWidth.Visible = true;

this.nudWidth.Visible = true;

this.lblOutlineColor.Visible = false;

this.btnOutlineColor.Visible = false;

break;

case esriSymbologyStyleClass.esriStyleClassFillSymbols:

this.lblAngle.Visible = false;

this.nudAngle.Visible = false;

this.lblSize.Visible = false;

this.nudSize.Visible = false;

this.lblWidth.Visible = true;

this.nudWidth.Visible = true;

this.lblOutlineColor.Visible = true;

this.btnOutlineColor.Visible = true;

break;

}

}

2.5     调用自定义符号选择器

通过以上操作,本符号选择器雏形已经完成,我们可以3sdnMap主窗体中调用并进行测试。如果您已经完成“直接调用ArcMap中的符号选择器”这一节,请注释axTOCControl1_OnDoubleClick事件响应函数里的代码,并添加如下代码。如果您是直接学习自定义符号选择器这一节的,请先添加axTOCControl1控件的OnDoubleClick事件,再添加如下事件响应函数代码:

   /// <summary>

/// 双击TOCControl控件时触发的事件

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void axTOCControl1_OnDoubleClick(object sender, ITOCControlEvents_OnDoubleClickEvent e)

{

esriTOCControlItem itemType = esriTOCControlItem.esriTOCControlItemNone;

IBasicMap basicMap = null;

ILayer layer = null;

object unk = null;

object data = null;

axTOCControl1.HitTest(e.x, e.y, ref itemType, ref basicMap, ref layer, ref unk, ref data);

if (e.button == 1)

{

if(itemType==esriTOCControlItem.esriTOCControlItemLegendClass)

{

//取得图例

ILegendClass pLegendClass = ((ILegendGroup)unk).get_Class((int)data);

//创建符号选择器SymbolSelector实例

SymbolSelectorFrm SymbolSelectorFrm = new SymbolSelectorFrm(pLegendClass, layer);

if (SymbolSelectorFrm.ShowDialog() == DialogResult.OK)

{

//局部更新主Map控件

m_mapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, null);

//设置新的符号

pLegendClass.Symbol = SymbolSelectorFrm.pSymbol;

//更新主Map控件和图层控件

this.axMapControl1.ActiveView.Refresh();

this.axTOCControl1.Refresh();

}

}

}

按F5编译运行,相信你已经看到自己新手打造的符号选择器已经出现在眼前了。当然,它还比较简陋,下面我们将一起把它做得更完美些。

时间: 2024-10-12 16:23:43

《ArcGIS Engine+C#实例开发教程》第七讲 图层符号选择器的实现的相关文章

《ArcGIS Engine+C#实例开发教程》第八讲 属性数据表的查询显示

原文:<ArcGIS Engine+C#实例开发教程>第八讲 属性数据表的查询显示 第一讲 桌面GIS应用程序框架的建立 第二讲 菜单的添加及其实现 第三讲 MapControl与PageLayoutControl同步 第四讲 状态栏信息的添加与实现 第五讲 鹰眼的实现 第六讲 右键菜单添加与实现 教程Bug及优化方案1 第七讲 图层符号选择器的实现1 第七讲 图层符号选择器的实现2 第八讲 属性数据表的查询显示 摘要:这一讲中,我们将实现图层属性数据表的查询显示.在ArcMap中,单击图层右

《ArcGIS Engine+C#实例开发教程》第三讲 MapControl与PageLayoutControl同步

原文:<ArcGIS Engine+C#实例开发教程>第三讲 MapControl与PageLayoutControl同步 摘要:在ArcMap中,能够很方面地进行MapView和LayoutView两种视图的切换,而且二者之间的数据是同步显示的.关于两种视图同步的实现方法有多种,可以使用ObjectCopy对象进行数据硬拷贝,而比较简单的方法莫过于二者共享一份地图了,这也是最常用的方法.  教程目录: 第一讲 桌面GIS应用程序框架的建立 第二讲 菜单的添加及其实现 第三讲 MapContr

《ArcGIS Engine+C#实例开发教程》第四讲 状态栏信息的添加与实现

原文:<ArcGIS Engine+C#实例开发教程>第四讲 状态栏信息的添加与实现 摘要:在上一讲中,我们完成了 MapControl 和PageLayoutControl两种视图的同步工作,本讲我们将完成状态栏信息的添加与实现.应用程序的状态栏一般用来显示程序的当前状态,当前所使用的工具. GIS应用程序一般也在状态栏显示当前光标的坐标.比例尺等信息.学习完本讲内容,您将学会状态栏编程的基本方法,并且能够在我们的程序的状态栏中添加且显示以下信息:当前所用工具信息.当前比例尺.当前坐标.  

《ArcGIS Engine+C#实例开发教程》第五讲 鹰眼的实现

原文:<ArcGIS Engine+C#实例开发教程>第五讲 鹰眼的实现 摘要:所谓的鹰眼,就是一个缩略地图,上面有一个矩形框,矩形框区域就是当前显示的地图区域,拖动矩形框可以改变当前地图显示的位置,改变矩形框的大小,可以改变当前地图的显示区域大小,从起到导航的作用.鹰眼是地图浏览中常用的功能之一.关于鹰眼的实现方式,最常用的是用一个 MapControl控件显示地图全图,并在上面画一个红色矩形框表示当前地图的显示范围,并实现鹰眼 MapControl 与主窗体的 MapControl 互动.

ArcGIS Runtime for Android开发教程V2.0(1)基本概念

原文地址: ArcGIS Runtime for Android开发教程V2.0(1)基本概念 - ArcGIS_Mobile的专栏 - 博客频道 - CSDN.NET http://blog.csdn.net/arcgis_mobile/article/details/8113183   1.基本概念 1.1 Android简介         2007年11月,Google推出移动操作系统Android,并宣称Android是首个为移动终端打造的真正开放和完整的移动操作系统.自此,基于And

Senparc.Weixin.MP SDK 微信公众平台开发教程(七):解决用户上下文(Session)问题

原文:Senparc.Weixin.MP SDK 微信公众平台开发教程(七):解决用户上下文(Session)问题 从这篇文章中我们已经了解了微信公众平台消息传递的方式,这种方式有一个先天的缺陷:不同用户的请求都来自同一个微信服务器,这使得常规的Session无法使用(始终面对同一个请求对象,况且还有对方服务器Cookie是否能保存的问题). 这就要求我们自己建立一套独立的对话上下文请求机制. 上一篇<Senparc.Weixin.MP SDK 微信公众平台开发教程(六):了解MessageHa

ArcGIS Runtime for Android开发教程V2.0(2)开发环境配置

原文地址: ArcGIS Runtime for Android开发教程V2.0(2)开发环境配置 - ArcGIS_Mobile的专栏 - 博客频道 - CSDN.NET http://blog.csdn.net/arcgis_mobile/article/details/8113948   2.开发环境配置 2.1 系统要求 1)      支持的操作系统 A.      Windows XP(32位).Vista(32/64位).Windows 7(32/64位) B.      Mac

ArcGIS Runtime for Android开发教程V2.0(3)基础篇---Hello World Map

原文地址: ArcGIS Runtime for Android开发教程V2.0(3)基础篇---Hello World Map - ArcGIS_Mobile的专栏 - 博客频道 - CSDN.NET http://blog.csdn.net/arcgis_mobile/article/details/8124005 通过上面章节,我们已经了解如何配置一个ArcGIS Runtime for Android开发环境,下面我们将介绍如何使用Eclipse创建一个ArcGIS移动项目Hello W

微信公众平台开发教程(七)安全策略

微信公众平台开发教程(七)安全策略 尽管处理微信请求的服务器,处于微信服务器的后端,但是安全问题依然不可小觑. 大概总结以下几个方面,希望引起注意. 一.设置高复杂度的Token,尽量隐藏服务地址URL URL:即为处理微信请求的链接地址Token:用户身份凭证 申请成为开发者或者修改URL\Token时,微信会通过Get请求访问URL,验证签名,其中需要Token. 过程相当于一次握手,如果握手成功,可进行后续的通信. 成为开发者后,我们也可以进行修改 面临的危险:  1.如URL和Token