ArcEngine:如何进行缩放图层、属性信息显示、状态栏显示?

01 前言

如果以后不是工作相关,我或许以后再难了解ArcEngine相关的GIS桌面软件二次开发的内容?

02 要求

  1. 创建窗体应用程序;(10分)
  2. 修改窗口标题为本人的“学号 姓名”;(5分)
  3. 添加主地图控件、图层树控件和数据表显示控件,并合理布局;(10分)
  4. 添加菜单和状态栏控件;(5分)
  5. 增加“打开地图文档”菜单功能,弹出对话框选择地图文档(*.mxd),在主地图控件中显示该地图;(10分)
  6. 鼠标在主地图控件中移动时,将鼠标对应的地图坐标显示在状态栏上;(10分)
  7. 地图显示范围发生改变时,将地图比例显示在状态栏上;(10分)
  8. 点击图层控件的图层项,将地图视图显示范围缩放到该图层范围;(10分)
  9. 在数据表显示控件中显示所选图层的属性;(20分)
  10. 撰写期末考查报告。(10分)

笔记本;WIndow11;VS2012;ArcEngine10.2

如果安装高版本的VS可能无法完美复现本博客,因为高版本VS如何创建基础版的应用,而是创建的完全0的空应用。

03 实现步骤和代码说明

3.1 创建窗体应用程序(创建项目)

在这里插入图片描述

初始界面如下:

在这里插入图片描述

在这里插入图片描述

如果不存在上述面板如下打开:

在这里插入图片描述

如此可以看到如下初始界面:

在这里插入图片描述

在这里插入图片描述

3.2 修改窗口标题为本人的“学号 姓名”

在这里插入图片描述

3.3 添加主地图控件、图层树控件和数据表显示控件,并合理布局

主地图控件和图层树控件已经在创建项目之后已经存在了,只是数据表(用于后续选中图层的属性信息显示)并没有,而且要与当前控件布局协调。

数据表使用DataGridView工具。

3.3.1 添加数据表DataGridView

在这里插入图片描述

3.3.2 调整布局

但是目前布局不合理,我们需要调整DataGridViewaxMapControl1(主地图控件)的空间位置。

修改DataGridViewDock属性为Bottom,这里就是用其他工具进行调整了,简单一些好了。

在这里插入图片描述

3.4 添加菜单和状态栏控件;

由于创建项目时已经帮助我们添加这些控件,因此我们无需重复操作,这里直接运行看看界面吧。

在这里插入图片描述

3.5 增加“打开地图文档”菜单功能,弹出对话框选择地图文档(*.mxd),在主地图控件中显示该地图;

这个功能实际上创建项目时也已经实现了,因此演示如下:

在这里插入图片描述

3.6 鼠标在主地图控件中移动时,将鼠标对应的地图坐标显示在状态栏上;

实际上也已经实现,这里不再说明

3.7 地图显示范围发生改变时,将地图比例显示在状态栏上

状态栏加一个用于显示比例尺:

在这里插入图片描述

监听范围更新事件:

在这里插入图片描述

事件代码如下:

private void axMapControl1_OnExtentUpdated(object sender, IMapControlEvents2_OnExtentUpdatedEvent e)
        {
            //当前比例尺
            string strScale = "   1:" + ((long)axMapControl1.MapScale).ToString() + "  ";
            // 在状态栏中进行格式化显示
            statusBarScale.Text = string.Format("{0}", strScale);
        }

实现效果如下:

在这里插入图片描述

3.8 点击图层控件的图层项,将地图视图显示范围缩放到该图层范围

显然,需要监听TOC图层树的鼠标点击事件:

在这里插入图片描述

事件代码如下:

// 当鼠标点击图层时, 实现图层缩放和属性获取显示两个功能
        private void axTOCControl1_OnMouseDown(object sender, ITOCControlEvents_OnMouseDownEvent e)
        {
            // 做鼠标点击位置检测-用于获取当前点击位置是否为图层以及获取点击的图层对象
            esriTOCControlItem itemType = esriTOCControlItem.esriTOCControlItemNone;  // 赋初值None
            IBasicMap basicMap = null;
            ILayer pCurLayer = null;
            object unk = null;
            object data = null;
            axTOCControl1.HitTest(e.x, e.y, ref itemType, ref basicMap, ref pCurLayer, ref unk, ref data);  // 检测点击位置, 返回给ref等

            // 如果点击的不是图层对象, 那么不进行任何操作
            if (itemType != esriTOCControlItem.esriTOCControlItemLayer)
            {
                return;
            }

            // 如果pCurLayer为空则不进行操作
            if (pCurLayer == null)
            {
                return;
            }

            // 获取当前点击图层的感兴趣区域范围
            IEnvelope env = pCurLayer.AreaOfInterest;  // 获取当前点击图层的范围
            // 当前选中图层的框为空, 那么不进行任何操作
            if ((env.IsEmpty) || (env == null))
            {
                return;
            }

            // 将主视图的范围显示为当前右键选中图层的范围, 实现缩放到当前图层的功能
            axMapControl1.Extent = env;
            // 显示当前图层属性(自定义一个query_feature_class函数进行操作, 传入当前点击图层变量)
            query_feature_class(pCurLayer);
        }

上述代码最后部分加入了一个自定义函数:

// 显示当前图层属性(自定义一个query_feature_class函数进行操作, 传入当前点击图层变量)
query_feature_class(pCurLayer);

注意:这是后续功能(显示选中图层的属性信息)的实现。

3.9 在数据表显示控件中显示所选图层的属性

我们主要实现前面的query_feature_class函数,代码如下:

// 实现选择所选图层属性功能
privatevoid query_feature_class(ILayer layer)
{
    // 获取空间过滤对象
    ISpatialFilter pSpatialFilter = new SpatialFilter();
    pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;
    pSpatialFilter.GeometryField = "Shape";

    // 将当前传入该函数的 layer 进行过滤
    IFeatureClass pFeatureClass = (layer as IFeatureLayer).FeatureClass;
    IFeatureCursor pFeatureCursor = pFeatureClass.Search(pSpatialFilter, true);
    if (pFeatureCursor == null)
    {
        dataGridView.DataSource = null;
    }
    else
    {
        // 将对象传入
        dataGridView.DataSource = cursor2table(pFeatureCursor);
    }
}

// 图层属性信息与DataGridView数据格式的转换
private DataTable cursor2table(IFeatureCursor pFeatureCursor)
{
    // 为DataGridView创建表头并赋值
    DataTable tbl = new DataTable();
    for (int ix = 0; ix < pFeatureCursor.Fields.FieldCount; ix++)
    {
        tbl.Columns.Add(pFeatureCursor.Fields.get_Field(ix).Name);
    }

    // 将所有要素一行一行的迭代传入DataGridView中
    IFeature pFeature = pFeatureCursor.NextFeature();
    while (pFeature != null)
    {
        DataRow row = tbl.NewRow();
        for (int ix = 0; ix < pFeatureCursor.Fields.FieldCount; ix++)
        {
            row[ix] = pFeature.get_Value(ix).ToString();
        }
        tbl.Rows.Add(row);

        pFeature = pFeatureCursor.NextFeature();
    }

    return tbl;  // 返回已经存有图层属性信息的DataGridView对象
}

04 完整代码和应用界面展示

如此所有功能实现,完整代码:

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;
using System.Runtime.InteropServices;

using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.ADF;
using ESRI.ArcGIS.SystemUI;

using ESRI.ArcGIS.Geometry;

namespace DropCurtain
{
    public sealed partial class MainForm : Form
    {
        #region class private members
        private IMapControl3 m_mapControl = null;
        private string m_mapDocumentName = string.Empty;
        #endregion

        #region class constructor
        public MainForm()
        {
            InitializeComponent();
        }
        #endregion

        private void MainForm_Load(object sender, EventArgs e)
        {
            //get the MapControl
            m_mapControl = (IMapControl3)axMapControl1.Object;

            //disable the Save menu (since there is no document yet)
            menuSaveDoc.Enabled = false;
        }

        #region Main Menu event handlers
        private void menuNewDoc_Click(object sender, EventArgs e)
        {
            //execute New Document command
            ICommand command = new CreateNewDocument();
            command.OnCreate(m_mapControl.Object);
            command.OnClick();
        }

        private void menuOpenDoc_Click(object sender, EventArgs e)
        {
            //execute Open Document command
            ICommand command = new ControlsOpenDocCommandClass();
            command.OnCreate(m_mapControl.Object);
            command.OnClick();
        }

        private void menuSaveDoc_Click(object sender, EventArgs e)
        {
            //execute Save Document command
            if (m_mapControl.CheckMxFile(m_mapDocumentName))
            {
                //create a new instance of a MapDocument
                IMapDocument mapDoc = new MapDocumentClass();
                mapDoc.Open(m_mapDocumentName, string.Empty);

                //Make sure that the MapDocument is not readonly
                if (mapDoc.get_IsReadOnly(m_mapDocumentName))
                {
                    MessageBox.Show("Map document is read only!");
                    mapDoc.Close();
                    return;
                }

                //Replace its contents with the current map
                mapDoc.ReplaceContents((IMxdContents)m_mapControl.Map);

                //save the MapDocument in order to persist it
                mapDoc.Save(mapDoc.UsesRelativePaths, false);

                //close the MapDocument
                mapDoc.Close();
            }
        }

        private void menuSaveAs_Click(object sender, EventArgs e)
        {
            //execute SaveAs Document command
            ICommand command = new ControlsSaveAsDocCommandClass();
            command.OnCreate(m_mapControl.Object);
            command.OnClick();
        }

        private void menuExitApp_Click(object sender, EventArgs e)
        {
            //exit the application
            Application.Exit();
        }
        #endregion

        //listen to MapReplaced evant in order to update the statusbar and the Save menu
        private void axMapControl1_OnMapReplaced(object sender, IMapControlEvents2_OnMapReplacedEvent e)
        {
            //get the current document name from the MapControl
            m_mapDocumentName = m_mapControl.DocumentFilename;

            //if there is no MapDocument, diable the Save menu and clear the statusbar
            if (m_mapDocumentName == string.Empty)
            {
                menuSaveDoc.Enabled = false;
                statusBarXY.Text = string.Empty;
            }
            else
            {
                //enable the Save manu and write the doc name to the statusbar
                menuSaveDoc.Enabled = true;
                statusBarXY.Text = System.IO.Path.GetFileName(m_mapDocumentName);
            }
        }

        private void axMapControl1_OnMouseMove(object sender, IMapControlEvents2_OnMouseMoveEvent e)
        {
            statusBarXY.Text = string.Format("{0}, {1}  {2}", e.mapX.ToString("#######.##"), e.mapY.ToString("#######.##"), axMapControl1.MapUnits.ToString().Substring(4));
        }

        private void axMapControl1_OnExtentUpdated(object sender, IMapControlEvents2_OnExtentUpdatedEvent e)
        {
            //当前比例尺
            string strScale = "   1:" + ((long)axMapControl1.MapScale).ToString() + "  ";
            // 在状态栏中进行格式化显示
            statusBarScale.Text = string.Format("{0}", strScale);
        }

        private void axTOCControl1_OnMouseDown(object sender, ITOCControlEvents_OnMouseDownEvent e)
        {
            // 做鼠标点击位置检测-用于获取当前点击位置是否为图层以及获取点击的图层对象
            esriTOCControlItem itemType = esriTOCControlItem.esriTOCControlItemNone;  // 赋初值None
            IBasicMap basicMap = null;
            ILayer pCurLayer = null;
            object unk = null;
            object data = null;
            axTOCControl1.HitTest(e.x, e.y, ref itemType, ref basicMap, ref pCurLayer, ref unk, ref data);  // 检测点击位置, 返回给ref等

            // 如果点击的不是图层对象, 那么不进行任何操作
            if (itemType != esriTOCControlItem.esriTOCControlItemLayer)
            {
                return;
            }

            // 如果pCurLayer为空则不进行操作
            if (pCurLayer == null)
            {
                return;
            }

            // 获取当前点击图层的感兴趣区域范围
            IEnvelope env = pCurLayer.AreaOfInterest;  // 获取当前点击图层的范围
            // 当前选中图层的框为空, 那么不进行任何操作
            if ((env.IsEmpty) || (env == null))
            {
                return;
            }

            // 将主视图的范围显示为当前右键选中图层的范围, 实现缩放到当前图层的功能
            axMapControl1.Extent = env;
            // 显示当前图层属性(自定义一个query_feature_class函数进行操作, 传入当前点击图层变量)
            query_feature_class(pCurLayer);
        }

        // 实现选择所选图层属性功能
        private void query_feature_class(ILayer layer)
        {
            // 获取空间过滤对象
            ISpatialFilter pSpatialFilter = new SpatialFilter();
            pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;
            pSpatialFilter.GeometryField = "Shape";

            // 将当前传入该函数的 layer 进行过滤
            IFeatureClass pFeatureClass = (layer as IFeatureLayer).FeatureClass;
            IFeatureCursor pFeatureCursor = pFeatureClass.Search(pSpatialFilter, true);
            if (pFeatureCursor == null)
            {
                dataGridView.DataSource = null;
            }
            else
            {
                // 将对象传入
                dataGridView.DataSource = cursor2table(pFeatureCursor);
            }
        }

        // 图层属性信息与DataGridView数据格式的转换
        private DataTable cursor2table(IFeatureCursor pFeatureCursor)
        {
            // 为DataGridView创建表头并赋值
            DataTable tbl = new DataTable();
            for (int ix = 0; ix < pFeatureCursor.Fields.FieldCount; ix++)
            {
                tbl.Columns.Add(pFeatureCursor.Fields.get_Field(ix).Name);
            }

            // 将所有要素一行一行的迭代传入DataGridView中
            IFeature pFeature = pFeatureCursor.NextFeature();
            while (pFeature != null)
            {
                DataRow row = tbl.NewRow();
                for (int ix = 0; ix < pFeatureCursor.Fields.FieldCount; ix++)
                {
                    row[ix] = pFeature.get_Value(ix).ToString();
                }
                tbl.Rows.Add(row);

                pFeature = pFeatureCursor.NextFeature();
            }

            return tbl;  // 返回已经存有图层属性信息的DataGridView对象
        }

    }
}

实现界面:

在这里插入图片描述

打开地图文档功能:

在这里插入图片描述

图层缩放和选中图层的属性信息显示:

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/169366.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

gitlab利用CI多工程持续构建

搭建CI的过程中有多个工程的时候&#xff0c;一个完美的构建过程往往是子工程上的更新(push 或者是merge)触发父工程的构建&#xff0c;这就需要如下建立一个downstream pipeline 子仓库1 .gitlab-ci.yml stages:- buildbuild_job:stage: buildtrigger:project: test_user/tes…

IDEA运行thymeleaf的html文件打开端口为63342且连不上数据库

这边贴apple.html代码 <!DOCTYPE html> <html xmlns:th"http://www.thymeleaf.org"> <head><meta charset"UTF-8"><title>User List</title> </head> <body> <h1>User List</h1> <table&…

Vuex 组件间通讯

组件间通讯 Vuex https://vuex.vuejs.org/zh/ 基本原理 数据提取到父级 // index 文件 import Vue from vue import Vuex from "vuex" import tab from ./tab // 引入 modulesVue.use(Vuex) // 全局引入// 创建 Vuex 实例 export default new Vuex.Store({modules: …

Win10 开始菜单、微软app和设置都打不开(未解决)

环境&#xff1a; Win10专业版 问题描述&#xff1a; Win10 开始菜单、微软app和设置都打不开,桌面个性话打开就报错&#xff0c;打开个性化该文件没有与之关联的程序来执行该操作 解决方案&#xff1a; 一般造成原因是MS-Settings文件系统错误 1.先重启电脑&#xff08;重…

深入解析序列模型:全面阐释 RNN、LSTM 与 Seq2Seq 的秘密

探索序列建模的基础知识和应用。 简介 序列建模是许多领域的一个重要问题&#xff0c;包括自然语言处理 (NLP)、语音识别和语音合成、时间序列预测、音乐生成和「生物信息学」。所有这些任务的共同点是它们需要坚持。接下来的事情的预测是基于历史的。例如&#xff0c;在“哈桑…

面试题-6

1.精灵图和base64的区别是什么&#xff1f; 精灵图:把多张小图整合到一张大图上,利用定位的一些属性把小图显示在页面上,当访问页面可以减少请求,提高加载速度 base64&#xff1a;传输8bit字节代码的编码方式,把原本二进制形式转为64个字符的单位&#xff0c;最后组成字符串 …

Linux 串口应用编程

1 串口 API Linux串口通信&#xff1a; 在 Linux 系统中&#xff0c;操作设备的统一接口就是&#xff1a; open/ioctl/read/write 。 对于 UART &#xff0c;又在 ioctl 之上封装了很多函数&#xff0c;主要是用来设置行规程。所以对于 UART &#xff0c;编程的套路就是…

iceberg学习笔记(2)—— 与Hive集成

前置知识&#xff1a; 1.了解hadoop基础知识&#xff0c;并能够搭建hadoop集群 2.了解hive基础知识 3.Iceberg学习笔记&#xff08;1&#xff09;—— 基础知识-CSDN博客 可以参考&#xff1a; Hadoop基础入门&#xff08;1&#xff09;&#xff1a;框架概述及集群环境搭建_TH…

Chrome添加扩展程序

Crx4Chrome 下载crx 打开扩展程序 如果拖动crx文件到扩展程序提示只能通过Chrome应用商店添加此项内容 修改crx文件后缀为zip并解压&#xff0c;再拖动到扩展程序

CXL崛起:2024启航,2025年开启新时代

在2019年&#xff0c;Intel主导联合多家阿里巴巴、Facebook(也就是改名后Meta)、谷歌、Dell、华为、思科、微软、HPE最初的八巨头&#xff0c;发布了新的互联协议CXL&#xff0c;全称Comupte Express Link。由于在服务器领域享有绝对领导地位&#xff0c;Intel一经号令&#xf…

消息中间的应用场景

1、异步处理 比如用户在电商网站下单&#xff0c;下单完成后会给用户推送短信或邮件&#xff0c;发短信和邮件的过程就可以异步完成。因为下单付款是核心业务&#xff0c;发邮件和短信并不属于核心功能&#xff0c;并且可能耗时较长&#xff0c;所以针对这种业务场景可以选择先…

【Qt开发流程】之程序主窗口

描述 就目前的应用程序而言&#xff0c;一般包含菜单栏、工具栏、状态栏、中央区域等。 qt窗口部件类图如下&#xff1a; 一个主窗口提供了一个构建应用程序用户界面的框架。 Qt有QMainWindow及其相关类来管理主窗口。 QMainWindow有自己的布局&#xff0c;可以向其中添加QTo…

测试之路,女孩子软件测试-职业规划建议,路就在脚下...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、测试岗是不是加…

Upwork 新手使用指南——如何快速在Upwork上接单

Upwork 这个自由职业平台不知道大家听说过没&#xff0c;在 Upwork&#xff0c;如果你是自由职业者&#xff0c;你可以接单&#xff1b;如果你是客户&#xff0c;你可以找人干活。但对于新手来说&#xff0c;怎么使用 Upwork 并且用好 Upwork 是一大难题。因此今天给大家分享 U…

Mistral 7B 比Llama 2更好的开源大模型 (四)

Mistral 7B在平衡高性能和保持大型语言模型高效的目标方面迈出了重要的一步。通过我们的工作,我们的目标是帮助社区创建更实惠、更高效、更高性能的语言模型,这些模型可以在广泛的现实世界应用程序中使用。 Mistral 7B在实践中,对于16K和W=4096的序列长度,对FlashAttentio…

Modbus转Profinet网关在污水处理系统中连接PLC和变频器Modbus通信案例

污水处理系统中使用Modbus转Profinet网关可以连接PLC和变频器&#xff0c;实现二者之间的通信。该网关的作用是将PLC与变频器之间的Modbus协议转换为Profinet协议&#xff0c;使两者可以相互沟通。在污水处理系统中&#xff0c;PLC控制污水处理的各个过程&#xff0c;而变频器则…

机器学习二元分类 二元交叉熵 二元分类例子

二元交叉熵损失函数 深度学习中的二元分类损失函数通常采用二元交叉熵&#xff08;Binary Cross-Entropy&#xff09;作为损失函数。 二元交叉熵损失函数的基本公式是&#xff1a; L(y, y_pred) -y * log(y_pred) - (1 - y) * log(1 - y_pred)其中&#xff0c;y是真实标签&…

【性能测试】稳定性测试要点-监控关键指标总结(超细整理)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、稳定性测试的要…

接口与抽象类的区别

Java中的接口&#xff08;Interface&#xff09;和抽象类&#xff08;Abstract Class&#xff09;都是实现抽象化的关键机制&#xff0c;但它们在用途和功能上有着明显的区别。以下是接口和抽象类之间的主要区别&#xff1a; 抽象类&#xff08;Abstract Class&#xff09; 含…

Docker之虚悬镜像(查看、删除)

虚悬镜像: 仓库名、标签都是的镜像&#xff0c;俗称dangling image 查看 docker image ls -f danglingtrue删除 虚悬镜像已经失去存在价值&#xff0c;可以删除 docker image prune