using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Display;
namespace WaterPipelineGIS2
{
public partial class Form1 : Form
{
private IFeatureLayer _selectedFeatureLayer;
private System.Drawing.Point _lastRightClickPosition;
private enum SelectionMode { None, Rectangle, Circle, Polygon, Polyline }
private SelectionMode currentMode = SelectionMode.None;
private enum MeasureMode { None, Area, Length, Point }
private MeasureMode currentMeasureMode = MeasureMode.None;
private IGeometry tempGeometry;
private IPointCollection pointCollection;
private Label lblMeasureResult;
private IGraphicsContainer _spatialSelectionGraphics; // 空间选择图形容器
private IGraphicsContainer _attributeHighlightGraphics; // 属性表高亮图形容器
public Form1()
{
InitializeComponent();
axMapControl1.OnMouseMove += new IMapControlEvents2_Ax_OnMouseMoveEventHandler(axMapControl1_OnMouseMove);
}
private void axMapControl1_OnMouseMove(object sender, IMapControlEvents2_OnMouseMoveEvent e)
{
// 获取地图坐标
double mapX = e.mapX;
double mapY = e.mapY;
// 格式化坐标显示(保留3位小数)
lblCoordinate.Text = string.Format("X: {0:F3} Y: {1:F3}", mapX, mapY);
// 立即刷新状态栏
statusStrip1.Refresh();
}
private void toolStripMenuItem2_Click(object sender, EventArgs e)
{
using (var rotateForm = new RotateForm())
{
if (rotateForm.ShowDialog() == DialogResult.OK)
{
try
{
axMapControl1.Rotation = rotateForm.RotationAngle;
axMapControl1.ActiveView.Refresh();
// 可选:更新状态栏
lblCoordinate.Text += " 旋转角度:{rotateForm.RotationAngle}°";
}
catch (Exception ex)
{
MessageBox.Show("旋转失败:{ex.Message}");
}
}
}
}
private void axTOCControl1_OnMouseDown(object sender, ITOCControlEvents_OnMouseDownEvent e)
{
if (e.button == 2) // 右键
{
// 保存点击位置(控件坐标系)
_lastRightClickPosition = new System.Drawing.Point(e.x, e.y);
ITOCControl2 tocControl = (ITOCControl2)axTOCControl1.Object;
// 修改点1:声明为接口类型并初始化为null
IBasicMap basicMap = null;
ILayer layer = null;
// 修改点2:使用Type.Missing代替new object()
object other = Type.Missing;
object index = Type.Missing;
esriTOCControlItem itemType = esriTOCControlItem.esriTOCControlItemNone;
// 修改点3:正确传递ref参数
tocControl.HitTest(e.x, e.y, ref itemType, ref basicMap, ref layer, ref other, ref index);
if (itemType == esriTOCControlItem.esriTOCControlItemLayer && layer != null)
{
contextMenuStripTOC.Show(axTOCControl1, e.x, e.y);
}
}
}
// 修改后(使用 MouseEventArgs)
private void openAttributeTableToolStripMenuItem_Click(object sender, EventArgs e)
{
ITOCControl2 tocControl = (ITOCControl2)axTOCControl1.Object;
IBasicMap basicMap = null;
ILayer layer = null;
object other = Type.Missing;
object index = Type.Missing;
esriTOCControlItem itemType = esriTOCControlItem.esriTOCControlItemNone;
// 获取当前鼠标位置(屏幕坐标系)
System.Drawing.Point screenPos = contextMenuStripTOC.PointToClient(Control.MousePosition);
// 转换为控件坐标系
System.Drawing.Point controlPos = axTOCControl1.PointToClient(Control.MousePosition);
tocControl.HitTest(
controlPos.X,
controlPos.Y,
ref itemType,
ref basicMap,
ref layer,
ref other,
ref index
);
IFeatureLayer featureLayer = layer as IFeatureLayer;
if (featureLayer != null)
{
_selectedFeatureLayer = featureLayer;
AttributeTableForm attrForm = new AttributeTableForm(
_selectedFeatureLayer,
this // 传递主窗体引用
);
attrForm.Show();
}
}
private void SetSelectionSymbol()
{
// 使用接口创建符号
ISimpleFillSymbol fillSymbol = new SimpleFillSymbol() as ISimpleFillSymbol;
fillSymbol.Color = GetRgbColor(255, 0, 0);
fillSymbol.Style = esriSimpleFillStyle.esriSFSSolid;
ISimpleLineSymbol lineSymbol = new SimpleLineSymbol() as ISimpleLineSymbol;
lineSymbol.Color = GetRgbColor(255, 255, 0);
lineSymbol.Width = 2;
fillSymbol.Outline = lineSymbol;
// 设置渲染器
if (_selectedFeatureLayer != null)
{
IGeoFeatureLayer geoLayer = (IGeoFeatureLayer)_selectedFeatureLayer;
ISimpleRenderer renderer = new SimpleRenderer() as ISimpleRenderer;
renderer.Symbol = (ISymbol)fillSymbol;
geoLayer.Renderer = (IFeatureRenderer)renderer;
axMapControl1.ActiveView.Refresh();
}
}
private IRgbColor GetRgbColor(int r, int g, int b)
{
IRgbColor color = new RgbColor() as IRgbColor; // 正确方式
color.Red = r;
color.Green = g;
color.Blue = b;
return color;
}
public void ActivateFeatureLayer(IFeatureLayer featureLayer)
{
if (featureLayer == null) return;
// 1. 设置当前活动图层
_selectedFeatureLayer = featureLayer;
// 2. 刷新地图显示(可选)
axMapControl1.ActiveView.Refresh();
// 3. 更新TOC控件的选中状态(可选)
axTOCControl1.Update();
}
// 修改 HighlightAndZoomToFeature 方法实现
public void HighlightAndZoomToFeature(IFeatureLayer featureLayer, int oid)
{
try
{
if (featureLayer == null || featureLayer.FeatureClass == null)
{
MessageBox.Show("图层或要素类无效!");
return;
}
// 获取要素并检查有效性
IFeature feature = featureLayer.FeatureClass.GetFeature(oid);
if (feature == null || feature.Shape == null)
{
MessageBox.Show("要素 OID {oid} 不存在或无几何!");
return;
}
IGeometry geometry = feature.Shape;
IEnvelope envelope = geometry.Envelope;
// 确保包络线有效
if (envelope.IsEmpty || envelope.Width == 0 || envelope.Height == 0)
{
envelope.Expand(10, 10, true); // 手动扩大点要素范围
}
else
{
envelope.Expand(1.5, 1.5, true);
}
// 缩放到要素范围
axMapControl1.Extent = envelope;
axMapControl1.ActiveView.ScreenDisplay.UpdateWindow();
// 高亮几何
HighlightGeometry(geometry);
}
catch (Exception ex)
{
MessageBox.Show("高亮要素失败: {ex.Message}");
}
}
public object _featureLayer { get; set; }
// 矩形选择
private void btnRectSelect_Click(object sender, EventArgs e)
{
currentMode = SelectionMode.Rectangle;
axMapControl1.CurrentTool = null;
}
// 圆形选择
private void btnCircleSelect_Click(object sender, EventArgs e)
{
currentMode = SelectionMode.Circle;
axMapControl1.CurrentTool = null;
}
// 多边形选择
private void btnPolygonSelect_Click(object sender, EventArgs e)
{
currentMode = SelectionMode.Polygon;
axMapControl1.CurrentTool = null;
}
// 折线选择
private void btnLineSelect_Click(object sender, EventArgs e)
{
currentMode = SelectionMode.Polyline;
axMapControl1.CurrentTool = null;
}
// 地图鼠标按下事件
private void axMapControl1_OnMouseDown(object sender, IMapControlEvents2_OnMouseDownEvent e)
{
try
{
IGeometry geometry = null;
switch (currentMode)
{
case SelectionMode.Rectangle:
// 绘制矩形(返回的是IEnvelope)
geometry = axMapControl1.TrackRectangle();
break;
case SelectionMode.Circle:
IEnvelope envelope = axMapControl1.TrackRectangle();
if (envelope.Width <= 0 || envelope.Height <= 0)
{
MessageBox.Show("请拖拽有效的矩形范围以创建圆形!");
return;
}
// 创建圆心点
IPoint center = new PointClass();
center.PutCoords(
(envelope.XMin + envelope.XMax) / 2,
(envelope.YMin + envelope.YMax) / 2
);
// 计算半径(取矩形宽高的平均值)
double radius = Math.Max(envelope.Width, envelope.Height) / 2;
// 创建圆形几何
ICircularArc circularArc = new CircularArcClass();
IConstructCircularArc constructArc = (IConstructCircularArc)circularArc;
constructArc.ConstructCircle(center, radius, true);
// 将圆弧转换为多边形
ISegmentCollection segColl = new PolygonClass();
segColl.AddSegment((ISegment)circularArc);
geometry = (IGeometry)segColl;
geometry.SpatialReference = axMapControl1.SpatialReference;
break;
case SelectionMode.Polygon:
// 绘制多边形
geometry = axMapControl1.TrackPolygon();
break;
case SelectionMode.Polyline:
// 绘制折线
geometry = axMapControl1.TrackLine();
break;
}
if (geometry != null)
{
PerformSpatialSelection(geometry);
HighlightGeometry(geometry);
}
}
catch (Exception ex)
{
MessageBox.Show("操作失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
// 执行空间选择
private void PerformSpatialSelection(IGeometry geometry)
{
try
{
IMap map = axMapControl1.Map;
if (map == null) return;
map.ClearSelection();
for (int i = 0; i < map.LayerCount; i++)
{
IFeatureLayer featureLayer = map.get_Layer(i) as IFeatureLayer;
if (featureLayer == null || !featureLayer.Valid || featureLayer.FeatureClass == null)
continue;
// 检查几何类型是否支持空间查询
if (geometry.GeometryType == esriGeometryType.esriGeometryPoint &&
featureLayer.FeatureClass.ShapeType != esriGeometryType.esriGeometryPoint)
continue;
ISpatialFilter filter = new SpatialFilterClass
{
Geometry = geometry,
GeometryField = featureLayer.FeatureClass.ShapeFieldName,
SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects
};
IFeatureSelection selection = (IFeatureSelection)featureLayer;
selection.SelectFeatures(filter, esriSelectionResultEnum.esriSelectionResultNew, false);
}
axMapControl1.Refresh(esriViewDrawPhase.esriViewGeoSelection, null, null);
}
catch (Exception ex)
{
MessageBox.Show("空间查询失败: {ex.Message}");
}
}
// 高亮显示选择图形(修复版)
private void HighlightGeometry(IGeometry geometry)
{
if (geometry == null || geometry.IsEmpty)
{
MessageBox.Show("几何无效!");
return;
}
IGraphicsContainer graphicsContainer = axMapControl1.Map as IGraphicsContainer;
graphicsContainer.DeleteAllElements(); // 清除旧图形
// 创建符号和元素
IElement element = null;
ISymbol symbol = null;
switch (geometry.GeometryType)
{
case esriGeometryType.esriGeometryPolygon:
case esriGeometryType.esriGeometryEnvelope:
ISimpleFillSymbol fillSymbol = new SimpleFillSymbolClass
{
Color = GetRgbColor(255, 0, 0, 80),
Style = esriSimpleFillStyle.esriSFSSolid
};
fillSymbol.Outline = new SimpleLineSymbolClass
{
Color = GetRgbColor(255, 0, 0),
Width = 2
};
symbol = (ISymbol)fillSymbol;
element = new PolygonElementClass();
break;
case esriGeometryType.esriGeometryPolyline:
ISimpleLineSymbol lineSymbol = new SimpleLineSymbolClass
{
Color = GetRgbColor(255, 0, 0),
Width = 3
};
symbol = (ISymbol)lineSymbol;
element = new LineElementClass();
break;
case esriGeometryType.esriGeometryPoint:
ISimpleMarkerSymbol markerSymbol = new SimpleMarkerSymbolClass
{
Color = GetRgbColor(255, 0, 0),
Size = 12,
Style = esriSimpleMarkerStyle.esriSMSCircle
};
symbol = (ISymbol)markerSymbol;
element = new MarkerElementClass();
break;
}
if (element != null && symbol != null)
{
element.Geometry = geometry;
graphicsContainer.AddElement(element, 0);
axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);
}
}
private IColor GetRgbColor(int p, int p_2, int p_3, int p_4)
{
throw new NotImplementedException();
}
// 创建颜色对象
private IRgbColor GetRGBColor(int r, int g, int b, int alpha = 255)
{
IRgbColor color = new RgbColorClass();
color.Red = r;
color.Green = g;
color.Blue = b;
color.Transparency = (byte)(255 - alpha);
return color;
}
// 清除选择
private void btnClearSelection_Click(object sender, EventArgs e)
{
axMapControl1.Map.ClearSelection();
IGraphicsContainer graphicsContainer = axMapControl1.Map as IGraphicsContainer;
graphicsContainer.DeleteAllElements();
axMapControl1.Refresh();
}
// 新增双击事件处理
private void axMapControl1_OnDoubleClick(object sender, IMapControlEvents2_OnDoubleClickEvent e)
{
if (currentMode != SelectionMode.None)
{
currentMode = SelectionMode.None;
axMapControl1.CurrentTool = null;
axMapControl1.MousePointer = esriControlsMousePointer.esriPointerDefault;
}
}
// 添加量测按钮点击事件
private void btnMeasureArea_Click(object sender, EventArgs e)
{
ResetMeasureMode(MeasureMode.Area);
lblMeasureResult.Text = "状态:绘制多边形(双击结束)";
}
private void btnMeasureLength_Click(object sender, EventArgs e)
{
ResetMeasureMode(MeasureMode.Length);
lblMeasureResult.Text = "状态:绘制折线(双击结束)";
}
private void btnMeasurePoint_Click(object sender, EventArgs e)
{
ResetMeasureMode(MeasureMode.Point);
lblMeasureResult.Text = "状态:移动鼠标查看坐标";
}
private void ResetMeasureMode(MeasureMode mode)
{
currentMeasureMode = mode;
ClearTempGraphics();
axMapControl1.CurrentTool = null;
axMapControl1.MousePointer = esriControlsMousePointer.esriPointerCrosshair;
}
private void ClearTempGraphics()
{
throw new NotImplementedException();
}
// 修改后的地图鼠标事件处理
private void axMapControl1_OnMouseDown2(object sender, IMapControlEvents2_OnMouseDownEvent e)
{
try
{
if (currentMeasureMode == MeasureMode.None) return;
IPoint currentPoint = axMapControl1.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(e.x, e.y);
switch (currentMeasureMode)
{
case MeasureMode.Area:
case MeasureMode.Length:
if (pointCollection == null)
{
// 🟢 根据模式创建不同几何类型
pointCollection = currentMeasureMode == MeasureMode.Area ?
(IPointCollection)new PolygonClass() :
(IPointCollection)new PolylineClass();
pointCollection.AddPoint(currentPoint);
}
pointCollection.AddPoint(currentPoint);
DrawTempGeometry();
break;
}
}
catch (Exception ex)
{
MessageBox.Show("操作错误:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void DrawTempGeometry()
{
throw new NotImplementedException();
}
}
}using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Geodatabase;
namespace WaterPipelineGIS2
{
public partial class AttributeTableForm : Form
{
private IFeatureLayer _featureLayer;
private Form1 _mainForm; // 主窗体引用
public AttributeTableForm(IFeatureLayer featureLayer, Form1 mainForm)
{
InitializeComponent();
_featureLayer = featureLayer;
_mainForm = mainForm;
// 绑定数据
BindData();
// 绑定行选择事件
dgvAttributes.SelectionChanged += DgvAttributes_SelectionChanged;
// 添加行双击事件
dgvAttributes.CellDoubleClick += (s, args) =>
{
if (args.RowIndex >= 0)
{
int oid = Convert.ToInt32(dgvAttributes.Rows[args.RowIndex].Cells[0].Value);
_mainForm.ActivateFeatureLayer(_featureLayer);
_mainForm.HighlightAndZoomToFeature(_featureLayer, oid);
}
};
}
private void DgvAttributes_SelectionChanged(object sender, EventArgs e)
{
if (dgvAttributes.SelectedRows.Count == 0)
return;
// 获取当前行的 OID
int oid = Convert.ToInt32(dgvAttributes.SelectedRows[0].Cells[0].Value);
// 激活主窗体的图层
_mainForm.ActivateFeatureLayer(_featureLayer);
// 调用主窗体的高亮方法(传递当前图层)
_mainForm.HighlightAndZoomToFeature(_featureLayer, oid);
}
private void BindData()
{
IFeatureCursor cursor = _featureLayer.FeatureClass.Search(null, true);
DataTable dataTable = new DataTable();
// 添加 OID 字段(关键修改:使用要素类的 OID 字段名)
dataTable.Columns.Add(_featureLayer.FeatureClass.OIDFieldName, typeof(int)); // 自动获取系统 OID 字段名
// 添加其他字段
for (int i = 0; i < cursor.Fields.FieldCount; i++)
{
IField field = cursor.Fields.get_Field(i);
if (field.Type == esriFieldType.esriFieldTypeOID) continue; // 跳过已添加的 OID 字段
dataTable.Columns.Add(field.Name, GetFieldType(field.Type));
}
// 填充数据
IFeature feature;
while ((feature = cursor.NextFeature()) != null)
{
DataRow row = dataTable.NewRow();
row[0] = feature.OID; // 直接使用 OID 属性
for (int i = 0; i < cursor.Fields.FieldCount; i++)
{
IField field = cursor.Fields.get_Field(i);
if (field.Type == esriFieldType.esriFieldTypeOID) continue;
row[field.Name] = feature.get_Value(i) ?? DBNull.Value;
}
dataTable.Rows.Add(row);
}
dgvAttributes.DataSource = dataTable;
}
// 辅助方法:将 ArcGIS 字段类型转换为 .NET 类型
private Type GetFieldType(esriFieldType fieldType)
{
switch (fieldType)
{
case esriFieldType.esriFieldTypeString: return typeof(string);
case esriFieldType.esriFieldTypeInteger: return typeof(int);
case esriFieldType.esriFieldTypeDouble: return typeof(double);
case esriFieldType.esriFieldTypeDate: return typeof(DateTime);
default: return typeof(string);
}
}
}
}
此代码能进行空间选择,但是绘制后会弹出报错窗口,且之前绘制后会暂时留下的红色区域不见了,如何解决