第12章-WinForms桌面应用开发

第12章:WinForms 桌面应用开发

12.1 MapBox 控件

12.1.1 添加到工具箱

  1. 安装 SharpMap.UI NuGet 包
  2. 右键工具箱 → 选择项 → 浏览 → 选择 SharpMap.UI.dll
  3. 勾选 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 桌面应用开发:

  1. MapBox 控件:添加、配置和使用 MapBox
  2. 事件处理:鼠标事件和地图事件
  3. 要素查询:点击查询和框选查询
  4. 要素高亮:高亮图层实现
  5. 图层控制:图层管理器控件
  6. 绘制功能:绘制点、线、面

下一章预告:第13章将介绍 WPF 桌面应用开发。

posted @ 2026-01-08 14:09  我才是银古  阅读(22)  评论(0)    收藏  举报