第12章-WinForms桌面应用开发
第12章:WinForms 桌面应用开发
12.1 MapBox 控件
12.1.1 添加到工具箱
- 安装
SharpMap.UINuGet 包 - 右键工具箱 → 选择项 → 浏览 → 选择 SharpMap.UI.dll
- 勾选 MapBox 和 MapImage 控件
12.1.2 基本使用
using System.Windows.Forms;
using SharpMap;
using SharpMap.Forms;
using SharpMap.Layers;
using SharpMap.Data.Providers;
using SharpMap.Styles;
public partial class MainForm : Form
{
private Map _map;
private MapBox _mapBox;
public MainForm()
{
InitializeComponent();
InitializeMap();
}
private void InitializeMap()
{
// 创建地图
_map = new Map(new Size(800, 600));
_map.BackColor = Color.White;
// 创建 MapBox 控件
_mapBox = new MapBox
{
Dock = DockStyle.Fill,
Map = _map
};
// 添加到窗体
this.Controls.Add(_mapBox);
// 加载数据
LoadLayers();
// 设置交互模式
_mapBox.ActiveTool = MapBox.Tools.Pan;
}
private void LoadLayers()
{
var layer = new VectorLayer("Countries");
layer.DataSource = new ShapeFile("countries.shp", true);
layer.Style = new VectorStyle
{
Fill = new SolidBrush(Color.LightGreen),
Outline = new Pen(Color.DarkGreen, 1),
EnableOutline = true
};
_map.Layers.Add(layer);
_map.ZoomToExtents();
}
}
12.1.3 交互工具
// 可用的交互工具
public enum MapBox.Tools
{
None, // 无工具
Pan, // 平移
ZoomIn, // 放大
ZoomOut, // 缩小
Query, // 查询
ZoomWindow, // 框选放大
DrawPoint, // 绘制点
DrawLine, // 绘制线
DrawPolygon // 绘制多边形
}
// 设置当前工具
_mapBox.ActiveTool = MapBox.Tools.Pan;
// 工具栏按钮事件
private void btnPan_Click(object sender, EventArgs e)
{
_mapBox.ActiveTool = MapBox.Tools.Pan;
}
private void btnZoomIn_Click(object sender, EventArgs e)
{
_mapBox.ActiveTool = MapBox.Tools.ZoomIn;
}
private void btnZoomOut_Click(object sender, EventArgs e)
{
_mapBox.ActiveTool = MapBox.Tools.ZoomOut;
}
private void btnZoomToExtents_Click(object sender, EventArgs e)
{
_map.ZoomToExtents();
_mapBox.Refresh();
}
12.2 事件处理
12.2.1 鼠标事件
private void InitializeEvents()
{
_mapBox.MouseMove += MapBox_MouseMove;
_mapBox.MouseClick += MapBox_MouseClick;
_mapBox.MouseDoubleClick += MapBox_MouseDoubleClick;
_mapBox.MouseWheel += MapBox_MouseWheel;
}
private void MapBox_MouseMove(object sender, MouseEventArgs e)
{
// 显示坐标
var worldPoint = _map.ImageToWorld(new PointF(e.X, e.Y));
toolStripStatusLabel.Text = $"坐标: {worldPoint.X:F6}, {worldPoint.Y:F6}";
}
private void MapBox_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && _mapBox.ActiveTool == MapBox.Tools.Query)
{
var worldPoint = _map.ImageToWorld(new PointF(e.X, e.Y));
QueryFeatures(worldPoint);
}
}
private void MapBox_MouseDoubleClick(object sender, MouseEventArgs e)
{
// 双击放大
var worldPoint = _map.ImageToWorld(new PointF(e.X, e.Y));
_map.Center = worldPoint;
_map.Zoom /= 2;
_mapBox.Refresh();
}
12.2.2 地图事件
_mapBox.MapRefreshed += MapBox_MapRefreshed;
_mapBox.MapViewOnChange += MapBox_MapViewOnChange;
_mapBox.MapZoomChanged += MapBox_MapZoomChanged;
_mapBox.MapCenterChanged += MapBox_MapCenterChanged;
private void MapBox_MapRefreshed(object sender, EventArgs e)
{
// 地图刷新后
UpdateScaleDisplay();
}
private void MapBox_MapViewOnChange(object sender)
{
// 视图变化时
UpdateScaleDisplay();
}
private void MapBox_MapZoomChanged(double zoom)
{
// 缩放变化时
lblZoom.Text = $"缩放: {zoom:F2}";
}
private void MapBox_MapCenterChanged(Coordinate center)
{
// 中心点变化时
lblCenter.Text = $"中心: {center.X:F4}, {center.Y:F4}";
}
private void UpdateScaleDisplay()
{
double scale = _map.MapScale;
lblScale.Text = $"比例尺: 1:{scale:N0}";
}
12.3 要素查询
12.3.1 点击查询
private void QueryFeatures(Coordinate point)
{
// 创建查询范围
double tolerance = _map.PixelWidth * 5;
var queryEnvelope = new Envelope(
point.X - tolerance, point.X + tolerance,
point.Y - tolerance, point.Y + tolerance);
var results = new List<FeatureDataRow>();
// 查询各图层
foreach (var layer in _map.Layers.OfType<VectorLayer>().Where(l => l.Enabled))
{
var ds = new FeatureDataSet();
layer.DataSource.ExecuteIntersectionQuery(queryEnvelope, ds);
if (ds.Tables.Count > 0)
{
results.AddRange(ds.Tables[0].Rows.Cast<FeatureDataRow>());
}
}
// 显示结果
if (results.Any())
{
ShowQueryResults(results);
}
else
{
MessageBox.Show("未查询到要素", "查询结果");
}
}
private void ShowQueryResults(List<FeatureDataRow> features)
{
var form = new QueryResultForm(features);
form.Show(this);
}
12.3.2 框选查询
_mapBox.GeometryDefined += MapBox_GeometryDefined;
private void MapBox_GeometryDefined(Geometry geometry)
{
if (_mapBox.ActiveTool == MapBox.Tools.Query)
{
var results = new List<FeatureDataRow>();
foreach (var layer in _map.Layers.OfType<VectorLayer>().Where(l => l.Enabled))
{
var ds = new FeatureDataSet();
layer.DataSource.ExecuteIntersectionQuery(geometry, ds);
if (ds.Tables.Count > 0)
{
results.AddRange(ds.Tables[0].Rows.Cast<FeatureDataRow>());
}
}
ShowQueryResults(results);
}
}
12.4 要素高亮
12.4.1 高亮图层
public class HighlightLayer
{
private readonly Map _map;
private VectorLayer _highlightLayer;
private readonly List<Geometry> _highlightedGeometries;
public HighlightLayer(Map map)
{
_map = map;
_highlightedGeometries = new List<Geometry>();
InitializeHighlightLayer();
}
private void InitializeHighlightLayer()
{
_highlightLayer = new VectorLayer("Highlight");
_highlightLayer.DataSource = new GeometryProvider(_highlightedGeometries);
_highlightLayer.Style = new VectorStyle
{
Fill = new SolidBrush(Color.FromArgb(100, 255, 255, 0)),
Outline = new Pen(Color.Red, 3),
EnableOutline = true,
PointColor = new SolidBrush(Color.Red),
PointSize = 12
};
_map.Layers.Add(_highlightLayer);
}
public void Highlight(Geometry geometry)
{
_highlightedGeometries.Clear();
_highlightedGeometries.Add(geometry);
_highlightLayer.DataSource = new GeometryProvider(_highlightedGeometries);
}
public void HighlightMultiple(IEnumerable<Geometry> geometries)
{
_highlightedGeometries.Clear();
_highlightedGeometries.AddRange(geometries);
_highlightLayer.DataSource = new GeometryProvider(_highlightedGeometries);
}
public void Clear()
{
_highlightedGeometries.Clear();
_highlightLayer.DataSource = new GeometryProvider(_highlightedGeometries);
}
}
12.5 图层控制
12.5.1 图层管理器控件
public class LayerManagerControl : UserControl
{
private CheckedListBox _layerList;
private Map _map;
private MapBox _mapBox;
public LayerManagerControl()
{
InitializeComponent();
}
private void InitializeComponent()
{
_layerList = new CheckedListBox
{
Dock = DockStyle.Fill,
CheckOnClick = true
};
_layerList.ItemCheck += LayerList_ItemCheck;
this.Controls.Add(_layerList);
}
public void BindMap(Map map, MapBox mapBox)
{
_map = map;
_mapBox = mapBox;
RefreshLayerList();
}
public void RefreshLayerList()
{
_layerList.Items.Clear();
for (int i = _map.Layers.Count - 1; i >= 0; i--)
{
var layer = _map.Layers[i];
_layerList.Items.Add(layer.LayerName, layer.Enabled);
}
}
private void LayerList_ItemCheck(object sender, ItemCheckEventArgs e)
{
string layerName = _layerList.Items[e.Index].ToString();
var layer = _map.Layers.FirstOrDefault(l => l.LayerName == layerName);
if (layer != null)
{
layer.Enabled = (e.NewValue == CheckState.Checked);
_mapBox.Refresh();
}
}
}
12.6 绘制功能
12.6.1 绘制点
private List<Coordinate> _drawnPoints = new List<Coordinate>();
private VectorLayer _drawLayer;
private void InitializeDrawLayer()
{
_drawLayer = new VectorLayer("Draw");
_drawLayer.DataSource = new GeometryProvider(new List<Geometry>());
_drawLayer.Style = new VectorStyle
{
PointColor = new SolidBrush(Color.Blue),
PointSize = 10
};
_map.Layers.Add(_drawLayer);
}
private void MapBox_GeometryDefined_Draw(Geometry geometry)
{
if (_mapBox.ActiveTool == MapBox.Tools.DrawPoint && geometry is Point point)
{
_drawnPoints.Add(point.Coordinate);
UpdateDrawLayer();
}
}
private void UpdateDrawLayer()
{
var factory = new GeometryFactory();
var geometries = _drawnPoints.Select(c => factory.CreatePoint(c) as Geometry).ToList();
_drawLayer.DataSource = new GeometryProvider(geometries);
_mapBox.Refresh();
}
12.6.2 绘制线和多边形
_mapBox.ActiveTool = MapBox.Tools.DrawLine;
// 或
_mapBox.ActiveTool = MapBox.Tools.DrawPolygon;
private void MapBox_GeometryDefined_Draw(Geometry geometry)
{
if (geometry is LineString line)
{
// 处理绘制的线
_drawnGeometries.Add(line);
}
else if (geometry is Polygon polygon)
{
// 处理绘制的多边形
_drawnGeometries.Add(polygon);
}
UpdateDrawLayer();
}
12.7 完整示例
12.7.1 主窗体设计
public partial class MainForm : Form
{
private Map _map;
private MapBox _mapBox;
private HighlightLayer _highlightLayer;
private ViewHistory _viewHistory;
public MainForm()
{
InitializeComponent();
InitializeMap();
InitializeToolbar();
InitializeStatusBar();
}
private void InitializeMap()
{
_map = new Map(new Size(800, 600));
_map.BackColor = Color.White;
_mapBox = new MapBox
{
Dock = DockStyle.Fill,
Map = _map
};
splitContainer.Panel2.Controls.Add(_mapBox);
_highlightLayer = new HighlightLayer(_map);
_viewHistory = new ViewHistory();
// 绑定事件
_mapBox.MouseMove += MapBox_MouseMove;
_mapBox.MouseClick += MapBox_MouseClick;
_mapBox.MapViewOnChange += (s) => { _viewHistory.Push(_map.Envelope); };
LoadData();
}
private void LoadData()
{
// 加载数据...
var layer = new VectorLayer("Data");
layer.DataSource = new ShapeFile("data.shp", true);
_map.Layers.Add(layer);
_map.ZoomToExtents();
}
// 工具栏按钮事件
private void btnPan_Click(object sender, EventArgs e) => SetActiveTool(MapBox.Tools.Pan);
private void btnZoomIn_Click(object sender, EventArgs e) => SetActiveTool(MapBox.Tools.ZoomIn);
private void btnZoomOut_Click(object sender, EventArgs e) => SetActiveTool(MapBox.Tools.ZoomOut);
private void btnQuery_Click(object sender, EventArgs e) => SetActiveTool(MapBox.Tools.Query);
private void btnZoomToExtents_Click(object sender, EventArgs e)
{
_map.ZoomToExtents();
_mapBox.Refresh();
}
private void btnPreviousView_Click(object sender, EventArgs e)
{
if (_viewHistory.CanUndo)
{
_map.ZoomToBox(_viewHistory.Undo());
_mapBox.Refresh();
}
}
private void SetActiveTool(MapBox.Tools tool)
{
_mapBox.ActiveTool = tool;
UpdateToolbarState(tool);
}
}
12.8 本章小结
本章介绍了 SharpMap WinForms 桌面应用开发:
- MapBox 控件:添加、配置和使用 MapBox
- 事件处理:鼠标事件和地图事件
- 要素查询:点击查询和框选查询
- 要素高亮:高亮图层实现
- 图层控制:图层管理器控件
- 绘制功能:绘制点、线、面
下一章预告:第13章将介绍 WPF 桌面应用开发。

浙公网安备 33010602011771号