ArcGIS Engine:鹰眼图的拓展功能-点击和矩形+坐标状态栏

news2024/11/18 5:34:09

目录

01 前言

02 鹰眼图的控制功能

03 显示当前鼠标的地理坐标


01 前言

说是拓展,不过是忘记了实验还有附加实验.这里补上.

前文不再赘述,上一节查看:ArcGIS Engine:视图菜单的创建和鹰眼图的实现_炒茄子的博客-CSDN博客

这里加上三个功能: 

为程序增加鹰眼(缩略图)显示功能,并扩展鹰眼功能

1)增加鹰眼图控制功能:

        在鹰眼图中点击鼠标,跳转主图到鼠标点击位置;

        在鹰眼图中绘制矩形,跳转主图到该矩形范围;

2)增加地图控件操作

        响应鼠标在地图上移动事件,将当前地理坐标显示在状态栏;

02 鹰眼图的控制功能

其实本质上鹰眼图中两个功能:点击鼠标和绘制矩形是捆绑在一块的功能我个人认为.

我们说一说点击鼠标, 然后主视图转到鼠标点击位置,这实际上就是监控鼠标按下时在鹰眼图对应的位置,然后找到主视图上对应位置将其显示在最中心。

而绘制矩形,看起来好像比较难,实际上就是继续监控鼠标松开(按下就是前面的点击鼠标,现在是松开)时在鹰眼图的位置,那么这里绘制矩形就是依据按下和松开两个位置构建一个矩形,然后这个矩形范围作为主视图显示的范围。

那么就需要监控两个事件,第一就是鼠标在鹰眼图按下时;第二就是鼠标在鹰眼图松开时;

但是每一个事件触发时我们应该做什么呢?按正常来想,我们应该是按下的时候(鼠标按下事件触发)完成第一个功能;然后松开的时候(鼠标松开事件触发,同时会利用前面鼠标按下事件触发时那个点位的信息)完成第二个功能。

但是实际上可能会这么:当用户按下鼠标,第一个功能触发,当用户松开鼠标第二个功能触发,所以两个功能会同时触发。所以我将做一些更改:

当鼠标按下,仅仅记录点位信息;

当鼠标松开,记录松开点位信息并判断与前面按下点位信息是否一致,如果一致执行第一个功能,否则执行第二个功能。

具体操作如下:

类似的,对于鼠标松开事件: 

 

两个功能的实现代码:

IPoint down_point;  //  类成员变量
public void EyeMapControl_OnMouseDown(object sender, IMapControlEvents2_OnMouseDownEvent e)
{
    // 当鼠标在鹰眼图上按下时,触发本事件
    // 该函数用于将主视图的显示从当前位置平移到鹰眼图中的鼠标点击的位置(平移操作放到了鼠标松开事件函数中, 因为要与鼠标绘制矩形然后主视图平移过去的功能区分)
    down_point = new PointClass();  // 实例化一个点对象
    down_point.X = e.mapX;  // 记录当前鼠标的X坐标
    down_point.Y = e.mapY;  // 记录当前鼠标的Y坐标
}

private void EyeMapControl_OnMouseUp(object sender, IMapControlEvents2_OnMouseUpEvent e)
{
    // 当鼠标在鹰眼图上松开时,触发本事件
    IPoint up_point = new PointClass();  // 实例化一个点对象
    up_point.X = e.mapX;
    up_point.Y = e.mapY;

    // 如果按下的鼠标为null说明用户在其它位置按下鼠标, 然后在鹰眼图中松开鼠标, 这不应该进行平移, 可能是误触
    if (down_point == null)
    {
        return;
    }

    if ((down_point.X == up_point.X) && (down_point.Y == up_point.Y))
    {
        // 如果按下和松开鼠标点位一致那么说明仅仅是点击
        MainMapControl.CenterAt(down_point);  // 将中心点移动到click_point点对象所在位置.

    }
    else
    {   // 如果不一致, 说明用户拉框了.我们将
        IEnvelope env = new EnvelopeClass();  // 实例化一个包络线对象
        double x_min = Math.Min(down_point.X, up_point.X);
        double x_max = Math.Max(down_point.X, up_point.X);
        double y_min = Math.Min(down_point.Y, up_point.Y);
        double y_max = Math.Max(down_point.Y, up_point.Y);
        env.PutCoords(x_min, y_min, x_max, y_max);

        MainMapControl.Extent = env;
    }

    MainMapControl.ActiveView.Refresh();  // 刷新
    down_point = null;  // 将鼠标按下的点位信息清除, 为下次准备
}

03 显示当前鼠标的地理坐标

这里就更简单了,当前鼠标的地理坐标,应该是显示当前鼠标在主视图上所在位置的坐标,所以只需要有一个事件监控鼠标移动就好了。

操作如下:

 

 我始终担心,我的状态栏名是CoordStatusLabel,但是你们的不一定是,你们可以在这里查看自己的状态栏名称:

代码:

// 当鼠标在主视图中移动时, 触发此事件
// 该函数用于在状态栏中显示当前鼠标对应的地理坐标信息
double x = e.mapX;
double y = e.mapY;
string units = MainMapControl.MapUnits.ToString().Substring(4);  // 去掉esri四个字符

//CoordStatusLabel.Text = string.Format("X: {0: .4f}; Y: {1: .4f}", x, y);
CoordStatusLabel.Text = string.Format("X: {0:.0000}; Y: {1:.0000}; 单位: {2}", x, y, units);

 所有完整代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using ESRI.ArcGIS.Controls;  // 使用其中的工具类(例如平移工具Pan等)
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Carto;  //  使用ILayer类
using ESRI.ArcGIS.Display;

namespace Ex2Twinborn
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            ESRI.ArcGIS.RuntimeManager.Bind(ESRI.ArcGIS.ProductCode.EngineOrDesktop);  // 解决版本不清晰问题
            InitializeComponent();
        }

        private void 放大ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // 该函数用于将鼠标状态切换为放大工具
            ControlsMapZoomInToolClass zoom_in = new ControlsMapZoomInToolClass();  //  实例化一个工具
            zoom_in.OnCreate(MainMapControl.Object);  // 告诉放大工具,它应该服务于谁,==> Map
            MainMapControl.CurrentTool = zoom_in;  // 将Map控件的当前使用工具切换为放大
        }

        private void 缩小ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // 当前函数用于将鼠标状态切换为缩小工具
            ControlsMapZoomOutToolClass zoom_out = new ControlsMapZoomOutToolClass();
            zoom_out.OnCreate(MainMapControl.Object);  // 将缩小工具的服务对象进行绑定
            MainMapControl.CurrentTool = zoom_out;  // 将Map控件的当前使用工具切换为缩小
        }

        private void 平移ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // 该函数用于将当前鼠标状态切换为平移工具
            ControlsMapPanToolClass pan = new ControlsMapPanToolClass();  //  如果不能正常运行, 请将引用下关于ESRI的所有引用的属性-嵌入互操作类型更改为false.
            pan.OnCreate(MainMapControl.Object);  // 告诉pan工具,你是在Map控件上进行工作的
            MainMapControl.CurrentTool = pan;  // 将Map控件当前的使用工具更改为平移工具
        }

        private void 全图ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // 该函数用于将当前Map进行全图显示-方法1
            MainMapControl.Extent = MainMapControl.FullExtent;
            MainMapControl.Refresh();
             方法2
            //ControlsMapFullExtentCommandClass full_extent = new ControlsMapFullExtentCommandClass();
            //full_extent.OnCreate(MainMapControl.Object);
            //full_extent.OnClick();
        }

        private void MainMapControl_OnMapReplaced(object sender, IMapControlEvents2_OnMapReplacedEvent e)
        {
            // 当主视图(MainMapControl)的内容被替换了(实际上此处仅仅是针对mxd文档被替换,对于一般数据的加载实际上不会触发此函数), 那么执行该部分函数
            // 该函数用于将主视图上的所有图层同步加载到鹰眼图中
            for (int ix=0; ix < MainMapControl.LayerCount; ix++)
            {
                ILayer layer = MainMapControl.get_Layer(ix);
                EyeMapControl.AddLayer(layer);
            }
            EyeMapControl.Extent = EyeMapControl.FullExtent;  // 全图显示
            EyeMapControl.Refresh();
            EyeMapControl.AutoMouseWheel = false;  // 不允许有滚动条
        }

        private void MainMapControl_OnExtentUpdated(object sender, IMapControlEvents2_OnExtentUpdatedEvent e)
        {
            // 当主视图的Extent范围发生变化, 那么触发此事件
            // 该函数用于更新鹰眼图中的矩形框(矩形框范围为主视图的Extent)
            IRectangleElement pRectangleElement = new RectangleElement() as IRectangleElement;  // 新建一个矩形框并更换类型
            IElement pEle = pRectangleElement as IElement;  //  再次更换类型
            IEnvelope pEnv = e.newEnvelope as IEnvelope;  // 获取主视图的范围边框并更换类型为包络线==> IEnvelope
            pEle.Geometry = pEnv;  // 设置刚刚创建的矩形边框的几何形状为刚刚主视图的范围的边框.

            IRgbColor pColor = new RgbColor();  // 实例化一个颜色对象
            pColor.Red = 200;  // 红色分量为200, 255表示完全红色
            pColor.Transparency = 255;  // 颜色的透明度, 255表示完全不透明

            ILineSymbol pLineSymbol = new SimpleLineSymbol();  // 实例化一个线对象
            pLineSymbol.Width = 2;  // 线的宽度为2
            pLineSymbol.Color = pColor;  // 线的颜色为刚刚设置的不饱和但完全不透明的红色

            IFillSymbol pFillSymbol = new SimpleFillSymbol();  // 创建一个填充符号
            pColor.Transparency = 0;  // 刚刚的颜色透明度修改为0也就是完全透明度
            pFillSymbol.Color = pColor;  // 填充色设置为刚刚的颜色, 实际上就是透明度的没有任何填充
            pFillSymbol.Outline = pLineSymbol;  // 但是填充符号的外边框(它是线)设置为刚刚的线对象

            IFillShapeElement pFillShapeElement = pRectangleElement as IFillShapeElement;
            pFillShapeElement.Symbol = pFillSymbol;

            IGraphicsContainer pGC = EyeMapControl.Map as IGraphicsContainer;  // 创建一个
            pGC.DeleteAllElements();  // 清除之前所有的图形\注记等等避免与后面新的图形发生冲突或者重叠.
            pGC.AddElement(pEle, 0);  // 添加矩形框在最底层

            IActiveView pActiveView = EyeMapControl.Map as IActiveView;
            pActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);
            // 刷新的图层是图形层(不包括加载的数据等)、刷新的对象(null表示图形层的所有对象)、刷新的空间范围(null表示整个鹰眼图范围)
        }

        private void MainMapControl_OnMapReplaced_1(object sender, IMapControlEvents2_OnMapReplacedEvent e)
        {
            // 当主视图(MainMapControl)的内容被替换了(实际上此处仅仅是针对mxd文档被替换,对于一般数据的加载实际上不会触发此函数), 那么执行该部分函数
            // 该函数用于将主视图上的所有图层同步加载到鹰眼图中
            for (int ix = 0; ix < MainMapControl.LayerCount; ix++)
            {
                ILayer layer = MainMapControl.get_Layer(ix);
                EyeMapControl.AddLayer(layer);
            }
            EyeMapControl.Extent = EyeMapControl.FullExtent;  // 全图显示
            EyeMapControl.Refresh();
            EyeMapControl.AutoMouseWheel = false;  // 不允许有滚动条
        }

        IPoint down_point;  //  类成员变量
        public void EyeMapControl_OnMouseDown(object sender, IMapControlEvents2_OnMouseDownEvent e)
        {
            // 当鼠标在鹰眼图上按下时,触发本事件
            // 该函数用于将主视图的显示从当前位置平移到鹰眼图中的鼠标点击的位置(平移操作放到了鼠标松开事件函数中, 因为要与鼠标绘制矩形然后主视图平移过去的功能区分)
            down_point = new PointClass();  // 实例化一个点对象
            down_point.X = e.mapX;  // 记录当前鼠标的X坐标
            down_point.Y = e.mapY;  // 记录当前鼠标的Y坐标
        }

        private void EyeMapControl_OnMouseUp(object sender, IMapControlEvents2_OnMouseUpEvent e)
        {
            // 当鼠标在鹰眼图上松开时,触发本事件
            IPoint up_point = new PointClass();  // 实例化一个点对象
            up_point.X = e.mapX;
            up_point.Y = e.mapY;

            // 如果按下的鼠标为null说明用户在其它位置按下鼠标, 然后在鹰眼图中松开鼠标, 这不应该进行平移, 可能是误触
            if (down_point == null)
            {
                return;
            }

            if ((down_point.X == up_point.X) && (down_point.Y == up_point.Y))
            {
                // 如果按下和松开鼠标点位一致那么说明仅仅是点击
                MainMapControl.CenterAt(down_point);  // 将中心点移动到click_point点对象所在位置.

            }
            else
            {   // 如果不一致, 说明用户拉框了.我们将
                IEnvelope env = new EnvelopeClass();  // 实例化一个包络线对象
                double x_min = Math.Min(down_point.X, up_point.X);
                double x_max = Math.Max(down_point.X, up_point.X);
                double y_min = Math.Min(down_point.Y, up_point.Y);
                double y_max = Math.Max(down_point.Y, up_point.Y);
                env.PutCoords(x_min, y_min, x_max, y_max);

                MainMapControl.Extent = env;
            }

            MainMapControl.ActiveView.Refresh();  // 刷新
            down_point = null;  // 将鼠标按下的点位信息清除, 为下次准备
        }

        private void MainMapControl_OnMouseMove(object sender, IMapControlEvents2_OnMouseMoveEvent e)
        {
            // 当鼠标在主视图中移动时, 触发此事件
            // 该函数用于在状态栏中显示当前鼠标对应的地理坐标信息
            double x = e.mapX;
            double y = e.mapY;
            string units = MainMapControl.MapUnits.ToString().Substring(4);  // 去掉esri四个字符

            //CoordStatusLabel.Text = string.Format("X: {0: .4f}; Y: {1: .4f}", x, y);
            CoordStatusLabel.Text = string.Format("X: {0:.0000}; Y: {1:.0000}; 单位: {2}", x, y, units);
        }
    }
}

最终效果:

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

unity脚本_Vector3 c#

接下来学习 相对世界坐标 首先我们给场景物体一个空物体 修改新建空物体名字为GameObjectFather 修改GameObjectFather坐标 修改GameObject2坐标 然后将GameObjectFahter设置成GameObject2的父物体 我们观察到子物体的坐标改变了但是 运行显示的相对世界坐标this.transform.po…

R语言教程课后习题答案(持续更新中~~)

R语言教程网址如下 https://www.math.pku.edu.cn/teachers/lidf/docs/Rbook/html/_Rbook/index.html 目录 source()函数可以运行保存在一个文本文件中的源程序 R向量下标和子集 数值型向量及其运算 日期功能 R因子类型 source()函数可以运行保存在一个文本文件中的源程序…

学信息系统项目管理师第4版系列18_采购管理

1. 协议 1.1. 合同 1.1.1. 国际合作的项目经理应牢记&#xff0c;无论合同规定如何详尽&#xff0c;文化和当地法律对合同及其可执行性均有影响 1.2. 服务水平协议&#xff08;SLA&#xff09; 1.3. 谅解备忘录 1.4. 协议备忘录&#xff08;MOA&#xff09; 1.5. 订购单 …

十天学完基础数据结构-第八天(哈希表(Hash Table))

哈希表的基本概念 哈希表是一种数据结构&#xff0c;用于存储键值对。它的核心思想是将键通过哈希函数转化为索引&#xff0c;然后将值存储在该索引位置的数据结构中。 哈希函数的作用 哈希函数是哈希表的关键部分。它将输入&#xff08;键&#xff09;映射到哈希表的索引位…

Python常用功能的标准代码

后台运行并保存log 1 2 3 4 5 6 7 8 9 nohup python -u test.py > test.log 2>&1 & #最后的&表示后台运行 #2 输出错误信息到提示符窗口 #1 表示输出信息到提示符窗口, 1前面的&注意添加, 否则还会创建一个名为1的文件 #最后会把日志文件输出到test.log文…

卷积神经网络-池化层和激活层

2.池化层 根据特征图上的局部统计信息进行下采样&#xff0c;在保留有用信息的同时减少特征图的大小。和卷积层不同的是&#xff0c;池化层不包含需要学习的参数。最大池化(max-pooling)在一个局部区域选最大值作为输出&#xff0c;而平均池化(average pooling)计算一个局部区…

卷积神经网络-卷积层

卷积神经网络 卷积神经网络&#xff08;convolutional neural network&#xff0c;CNN&#xff09;是一类包含卷积计算且具有深度结构的前馈神经网络&#xff0c;是深度学习的代表算法之一。卷积神经网络具有表征学习能力&#xff0c;能够按其阶层结构对输入信息进行平移不变分…

H5移动端购物商城系统源码 小型商城全新简洁风格全新UI 支持易支付接口

一款比较简单的 H5 移动端购物商城系统源码&#xff0c;比较适合单品商城、小型商城使用。带有易支付接口。 源码下载&#xff1a;https://download.csdn.net/download/m0_66047725/88391704 源码下载2&#xff1a;评论留言或私信留言

【Spring笔记03】Spring依赖注入各种数据类型

这篇文章&#xff0c;详细介绍一下Spring框架中如何注入各种数据类型&#xff0c;包含&#xff1a;注入基本数据类型、数组、集合、Map映射、Property属性、注入空字符串、注入null值、注入特殊字符等内容&#xff0c;以及如何使用命名空间进行依赖注入。 目录 一、注入各种数据…

云原生Kubernetes:简化K8S应用部署工具Helm

目录 一、理论 1.HELM 2.部署HELM2 3.部署HELM3 二、实验 1.部署 HELM2 2.部署HELM3 三、问题 1.api版本过期 2.helm初始化报错 3.pod状态为ImagePullBackOff 4.helm 命令显示 no repositories to show 的错误 5.Helm安装报错 6.git命令报错 7.CentOS 7 下git c…

互联网Java工程师面试题·Elasticsearch 篇·第一弹

目录 1、elasticsearch 了解多少&#xff0c;说说你们公司 es 的集群架构&#xff0c;索引数据大小&#xff0c;分片有多少&#xff0c;以及一些调优手段 。 1.1 设计阶段调优 1.2 写入调优 1.3 查询调优 1.4 其他调优 2、elasticsearch 的倒排索引是什么 3、elastic…

ToDoList使用自定义事件传值

MyTop与MyFooter与App之间传递数据涉及到的就是子给父传递数据&#xff0c;MyList和MyItem与App涉及到爷孙传递数据。 之前的MyTop是使用props接收App传值&#xff0c;然后再在methods里面调用&#xff0c;现在使用自定义事件来处理子组件和父组件之间传递数据。 图是之前的…

新款UI动态壁纸头像潮图小程序源码

新款UI动态壁纸头像潮图小程序源码&#xff0c;不需要域名服务器&#xff0c;直接添加合法域名&#xff0c;上传发布就能使用。 可以对接开通流量主&#xff0c;个人也能运营&#xff0c;不需要服务器源码完整。整合头像&#xff0c;动态壁纸&#xff0c;文案功能齐全。 源码…

代码随想录Day12 二叉树 LeetCode T102二叉树的层序遍历 T226 翻转二叉树 T101 对称二叉树

本文思路和详细讲解来自于:代码随想录 (programmercarl.com) LeetCode T102 二叉树的层序遍历 题目链接:102. 二叉树的层序遍历 - 力扣&#xff08;LeetCode&#xff09; 题目思路: 本题使用队列辅助完成,讲解主要函数CheckOrder:首先判断root是否为空,是就直接返回,然后创建…

芯驰D9评测(3)--建立开发环境

1. 建立交叉编译链接环境 官网下载的SDK包中就有交叉工具链&#xff0c;米尔提供的这个 SDK 中除了包含各种源代码外还提供了必要的交叉工具链&#xff0c;可以直接用于编译应用程序等。 用户可以直接使用次交叉编译工具链来建立一个独立的开发环境&#xff0c;可单独编译…

发光文字跟随鼠标

效果展示 CSS / JavaScript 知识点 background-image 绘制网格背景filter 属性的运用onmousemove 事件运用getBoundingClientRect 方法的运用 实现页面基础结构 <!-- 光标 --> <div class"cursour"></div>实现网格背景样式 body {min-height: …

如何用 Tana AI 一站式批量润色整理音频笔记?

&#xff08;注&#xff1a;本文为小报童精选文章&#xff0c;已订阅小报童或加入知识星球「玉树芝兰」用户请勿重复付费&#xff09; 用好 Tana AI Builder &#xff0c;充分体验和发挥 AI 工作流的强大性能。 痛点 作为一个足够懒惰的写作者&#xff0c;我对音频转文本这事儿…

智慧公厕如何实现?

随着城市化进程的加速&#xff0c;人们对公共设施的需求也日益增长。而公厕&#xff0c;作为城市基础设施的一部分&#xff0c;扮演着重要的角色。然而&#xff0c;传统的公厕存在着诸多问题&#xff0c;例如管理不善、环境脏乱等&#xff0c;给人们的生活带来了不便。为了改善…

笔试强训Day13

T1&#xff1a;跳石板 [小易来到了一条石板路前&#xff0c;每块石板上从1挨着编号为&#xff1a;1、2、3....... 这条石板路要根据特殊的规则才能前进&#xff1a;对于小易当前所在的编号为K的 石板&#xff0c;小易单次只能往前跳K的一个约数(不含1和K)步&#xff0c;即跳…

【LeetCode刷题笔记】双指针

剑指 Offer 21.调整数组顺序使奇数位于偶数前面 解题思路&#xff1a; 对撞指针 &#xff0c; 从左边不停的找第一个偶数&#xff0c;从右边不停的找第一个奇数 &#xff0c;找到后 交换 两者位置 本题与【905. 按奇偶排序数组】几乎雷同。 剑指 Offer 57.和为s的两个数字 本题…