做ArcGIS Add-In开发,需要在ArcMap中数据视图的左上角加一个上标,如果上标与数据中的地名图层重合,则放在右上角.
上标通过ITextElement,IElement,ITextSymbol等接口实现.
想当然的以为文本元素的定位点为左下角点或者右下角点,结果实验了半天,文字注记的位置一直匪夷所思.
以为之间的参数传输错误,下载了个像素三角尺,一边调试一边量屏幕的像素,发现这个定位点似乎是在文字的中下部的位置,
可是在ArcMap中用绘制工具绘制的文本,定位点似乎是在左下角点.
搞不明白,只能想办法解决,解决思路如下:
在屏幕的中间位置绘制TextElement,获取文本元素的Envelope对象,计算该Envelope对象的左上角点至ArcMap的左上角点
的像素坐标差,或Envelope的右上角点至ArcMap的右上角点的像素坐标差,根据计算出的像素坐标差,对之前绘制的TextElement
的定位点进行修正,更新TextElement.经过测试,结果满足要求.
核心代码如下:
IElement pEle = null;
pAv = pMap as IActiveView;
IGraphicsContainer pgc = pMap as IGraphicsContainer;
bool b_Cover = false;
if (SetPanel.addUpperTxt)
{
if (string.IsNullOrEmpty(SetPanel.locationTxt))
{
MessageBox.Show("无上标文字,请输入或选择字段后重新截图");
return;
}
//在当前视图位置左上角绘制上标文字
IPoint pntLocation = new PointClass(); int pixelY =; //SetPanel.VerOffset + (int)fontsize;
int pixelX =; //SetPanel.HorOffset + (SetPanel.locationTxt.Length) * (int)fontsize;
pntLocation = pAv.ScreenDisplay.DisplayTransformation.ToMapPoint(pixelX, pixelY); ITextElement pTxtEle = new TextElementClass();
ITextSymbol ptxtSymbol = new TextSymbolClass();
ptxtSymbol.Font.Name = "宋体";
IRgbColor pColor = new RgbColorClass();
pColor.Blue = ;
pColor.Red = ;
pColor.Green = ;
ptxtSymbol.Color = pColor;
ptxtSymbol.Size = fontsize;
ptxtSymbol.Font.Bold = true;
pTxtEle.Symbol = ptxtSymbol; pTxtEle.Text = SetPanel.locationTxt; pEle = pTxtEle as IElement;
pEle.Geometry = pntLocation;
pgc.AddElement(pEle, );
pAv.PartialRefresh(esriViewDrawPhase.esriViewGraphics,null,null);
IEnvelope pNewEnv = new EnvelopeClass();
pEle.QueryBounds(pAv.ScreenDisplay,pNewEnv);
int currentPixelX, currentPixelY;
pAv.ScreenDisplay.DisplayTransformation.FromMapPoint(pNewEnv.UpperLeft, out currentPixelX, out currentPixelY);
int txtLocationX = pixelX + SetPanel.HorOffset - currentPixelX;
int txtLocationY = pixelY + SetPanel.VerOffset - currentPixelY;
pEle.Geometry = pAv.ScreenDisplay.DisplayTransformation.ToMapPoint(txtLocationX, txtLocationY);
pAv.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);
pEle.QueryBounds(pAv.ScreenDisplay, pNewEnv);
ISegmentCollection segCol = new PolygonClass();
segCol.SetRectangle(pNewEnv); //判断是否覆盖 if (IsCoverOrNot((IPolygon)segCol, pMap))
{
pAv.ScreenDisplay.DisplayTransformation.FromMapPoint(pNewEnv.UpperRight, out currentPixelX, out currentPixelY); ESRI.ArcGIS.esriSystem.tagRECT Rect = pAv.ExportFrame;
int activeViewWidth = Rect.right - Rect.left;
//定位点校正
txtLocationX = txtLocationX+activeViewWidth-SetPanel.HorOffset-currentPixelX;
//txtLocationY = pixelY + SetPanel.VerOffset - currentPixelY;
pEle.Geometry = pAv.ScreenDisplay.DisplayTransformation.ToMapPoint(txtLocationX, txtLocationY);
pEle.QueryBounds(pAv.ScreenDisplay, pNewEnv);
segCol = new PolygonClass();
segCol.SetRectangle(pNewEnv);
if (IsCoverOrNot((IPolygon)segCol, pMap))
{
b_Cover = true;
MessageBox.Show("注记与小地名图层存在压盖,请调整视图");
}
} pgc.UpdateElement(pEle);
}