最近在做仿ArcGIS的标注功能,刚刚完成了,虽然说授之以鱼不如授之以渔,但是恕在下实在是思路文笔皆为下下,所以就掺杂着写吧!PS:某些非主要功能进行了省略!
- 开发环境
IDE:VS 2013 Ultimate
语言:C#
AE:10.0
- 时间
连学代玩大概两周左右吧。
- 代码量
初步估计接近3000行左右。
- 说明
此代码完全供初学者参考学习,这个地方主要介绍我实现的效果与功能,并不会有完整的代码,如果有需要详情请留言或者加qq:732344647
前言
我们使用ArcMap时,右键图层选择属性,再选择标注就基本上是我们功能的样式了,我去掉了下图红色框框的两个项目。
红色方框1不要是因为我们的每个图层生成时都会自动生成一个Deafaut名称的标注方式,而我们还可以生成其他的标注方式分别来给同一图层的不同要素进行标注样式设置,我们关注于标注样式的自定义功能而不是功能的全面,所以暂时省略;
红色方框2是我觉得此功能实用性太低,没人会去自己重新画一个符号的,当然主要原因是我没想明白它是怎么实现的!
下面这个图是我自己实现的:
文本字符串-表达式
这部分需要注意的关键点是标注表达式的验证问题,这里主要需要使用的接口是IAnnotationExpressionEngine和IAnnotationExpressionParser,下面来看看代码片段:
IAnnotationExpressionEngine pAnnotationExpressionEngine = this.mLabelEngineLayerProperties.ExpressionParser;
IAnnotationExpressionParser pAnnotationExpressionParser = pAnnotationExpressionEngine.SetExpression("", strExpression);
IFeature pFeature = GetOneFeature();//获取到当前图层的某个要素
if (pFeature == null)
{
MessageBox.Show("未找到要素,无法验证表达式。","警告",MessageBoxButtons.OK,MessageBoxIcon.Exclamation);
return;
}
int number = 0;
int line = 0;
string description = "";
pAnnotationExpressionParser.LastError(ref number, ref line, ref description);
if (number >0)
{
MessageBox.Show("表达式存在错误,请修改表达式 , 然后再试!","警告",MessageBoxButtons.OK,MessageBoxIcon.Error);
return;
}
else
{
string strLabel = pAnnotationExpressionParser.FindLabel(pFeature);//找到指定要素的标注显示样式
FrmLabelVerifyExpression frm = new FrmLabelVerifyExpression(strLabel);
frm.ShowDialog(this);
}
比例范围
这个功能也没什么特殊的,就是当缩小与放大全部为无的时候,其实相当于radiobutton选择了与要素图层相同的比例范围。
标注样式
这个功能与首界面的样式设置基本差不多,先说标注样式功能:
红色方框使用的是AE的样式控件,加载的样式文件Style也是ESRI自带的文件,不知道是不是我使用的问题还是怎样,显示预定义样式还是有问题,目前这个问题我并没有找到解决方案;
首界面样式设置
红色方框1与2都是使用button实现的,combobox使用WindowsAPI设置为ReadOnly,但是只读之后的背景颜色怎么代码编写有待研究。
红色方框三是字体的尺寸,这里有一个很奇怪的问题,在ITextSymbol.Size与ITextSymbol.Font.Size两个属性中,前者是double型的后者是decimal,但是在你设置了值以后,前者如果与后者不同,前者是按照后者的大小重新设置的,也就是说实际的尺寸由ITextSymbol.Font.Size决定。
这里还有两点要注意:1.像ITextSymbol.Font.Size=num连续赋值是不能真正的改变属性值得,必须先将font引用出来;2.ITextSymbol.Font.Size是IFontDisp类型的,当我们给Size赋值的时候,经常会出现自动变成增加或者减去0.25的情况,如赋值10,得到的就是9.75,并不是double与decimal精度的问题,是这个属性的问题,如果哪位大神知道为什么,请赐教!
总体来说这个功能也不复杂,就是button的font赋值是必须new一个新的font对象的,大家使用的时候可以仔细参看帮助文档。
放置属性
这个功能相对较为复杂,因为有点、线、面三种情况;这里需要注意的是三个图层的标注要素属性是可读可写的,所以我们需要根据图层的Shape类型来判断一下当前的标注要素类型是否为正确的,否则需要改过来
private void SetFeatureTypeByShapeType()
{
if (this.mFeatureLayer.FeatureClass.ShapeType == esriGeometryType.esriGeometryPoint)
{
if (!(this.mBasicOverposterLayerProperties.FeatureType == esriBasicOverposterFeatureType.esriOverposterPoint))
{
this.mBasicOverposterLayerProperties.FeatureType = esriBasicOverposterFeatureType.esriOverposterPoint;
}
}
else if (this.mFeatureLayer.FeatureClass.ShapeType == esriGeometryType.esriGeometryPolyline)
{
if (!(this.mBasicOverposterLayerProperties.FeatureType == esriBasicOverposterFeatureType.esriOverposterPolyline))
{
this.mBasicOverposterLayerProperties.FeatureType = esriBasicOverposterFeatureType.esriOverposterPolyline;
}
}
else if(this.mFeatureLayer.FeatureClass.ShapeType==esriGeometryType.esriGeometryPolygon)
{
if (!(this.mBasicOverposterLayerProperties.FeatureType == esriBasicOverposterFeatureType.esriOverposterPolygon))
{
this.mBasicOverposterLayerProperties.FeatureType = esriBasicOverposterFeatureType.esriOverposterPolygon;
}
}
else
{
this.mBasicOverposterLayerProperties.FeatureType = esriBasicOverposterFeatureType.esriOverposterPolygon;
}
}
上图!
1.点总体的显示样式:
围绕点放置:
因为点放置有4种情况,主要使用的还是围绕点放置,这里的所有图片都是从ArcMap中截图过来的!
2.面的功能显示窗体
3.线的功能显示窗体
线放置的总体逻辑较为复杂,而且参考文档中关于方向的解释并不是那么清晰,可能我英语差吧…
总体来说,线要素的设置相对复杂,所以需要考虑的逻辑也就越多,也就越繁琐,但是没有什么比较深奥的东西,慢慢研究就可以研究出来了。
总结
总体来说,在开发过程中并没有遇到特别难的问题,主要是难得问题也没解决,但是又无伤大雅;1. 需要注意的主要有一点,就是AE的变量赋值时不能连续引用,例如:
ITextSymbol.Font.Size=num;//错误
IFontDisp mFont=ITextSymbol.Font;//正确
mFont.Size=num;
2. 需要继续改进的就是控件的重写,因为自带的控件在有些地方确实使用不是很方便!所以需要研究下控件的重写与定制。