AE学习笔记之右键菜单的添加与实现

        ArcGIS Engine 中自定义了一些添加命令、工具和菜单的基类,在需要写相应函数的时候可以直接很方便的添加。

我在前面的文章里面有一节讲述过如何添加控件命令:http://blog.csdn.net/my_lord_/article/details/52599153   。本节讲述一下右键菜单的实现,右键菜单也就是单击鼠标右键时弹出的一个菜单项。主体也就是新建一个IToolbarMenu m_MenuMap 接口,将自定义的命令添加进去,最后在鼠标右键的响应函数中弹出即可。具体流程与代码如下:

1、添加变量,在Form1的类中。

#region Right Button Menu Class Memble
        //TOCControl控件变量
        private ITOCControl2 m_TocControl = null;
        //TOCControl中Map菜单
        private IToolbarMenu m_MenuMap = null;
        //TOCControl中图层菜单
        private IToolbarMenu m_MenuLayer = null;

        #endregion

2、添加命令函数。

        命令函数的具体添加过程就不再这里复述了,不太清楚地可以翻一下我前面的文章。这里贴上一些代码:

ZoomToLayer 命令:

 /// <summary>
    /// 放大至整个图层
    /// </summary>
    public sealed class ZoomToLayer : BaseCommand
    {
        private IMapControl3 m_mapControl;


        public ZoomToLayer()
        {
            base.m_caption = "Zoom To Layer";
        }


        public override void OnClick()
        {
            ILayer layer = (ILayer)m_mapControl.CustomProperty;
            m_mapControl.Extent = layer.AreaOfInterest;
        }


        public override void OnCreate(object hook)
        {
            m_mapControl = (IMapControl3)hook;
        }
    }

RemoveLayer 命令:

 /// <summary>
    /// 删除图层
    /// </summary>
    public sealed class RemoveLayer : BaseCommand
    {
        private IMapControl3 m_mapControl;


        public RemoveLayer()
        {
            base.m_caption = "Remove Layer";
            
        }


        public override void OnClick()
        {
            ILayer layer = (ILayer)m_mapControl.CustomProperty;
            m_mapControl.Map.DeleteLayer(layer);
        }


        public override void OnCreate(object hook)
        {
            m_mapControl = (IMapControl3)hook;
        }


    }


LayerVisibility 命令:

 /// <summary>
    /// 图层可视控制
    /// </summary>
    public sealed class LayerVisibility : BaseCommand, ICommandSubType
    {
        private IHookHelper m_hookHelper = new HookHelperClass();
        private long m_subType;


        public LayerVisibility()
        {
        }

        public override void OnClick()
        {
            for (int i = 0; i <= m_hookHelper.FocusMap.LayerCount - 1; i++)
            {
                if (m_subType == 1) m_hookHelper.FocusMap.get_Layer(i).Visible = true;
                if (m_subType == 2) m_hookHelper.FocusMap.get_Layer(i).Visible = false;
            }
            m_hookHelper.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, null);
        }

        public override void OnCreate(object hook)
        {
            m_hookHelper.Hook = hook;
        }

        public int GetCount()
        {
            return 2;
        }

        public void SetSubType(int SubType)
        {
            m_subType = SubType;
        }

        public override string Caption
        {
            get
            {
                if (m_subType == 1) return "Turn All Layers On";
                else return "Turn All Layers Off";
            }
        }

        public override bool Enabled
        {
            get
            {
                bool enabled = false; int i;
                if (m_subType == 1)
                {
                    for (i = 0; i <= m_hookHelper.FocusMap.LayerCount - 1; i++)
                    {
                        if (m_hookHelper.ActiveView.FocusMap.get_Layer(i).Visible == false)
                        {
                            enabled = true;
                            break;
                        }
                    }
                }
                else
                {
                    for (i = 0; i <= m_hookHelper.FocusMap.LayerCount - 1; i++)
                    {
                        if (m_hookHelper.ActiveView.FocusMap.get_Layer(i).Visible == true)
                        {
                            enabled = true;
                            break;
                        }
                    }
                }
                return enabled;
            }
        }
    }


这个里面做了几个处理,在这里描述一下:首先,这个命令的作用就是如果SubType为1时,设置Caption为Turn All  Layer On ,2的话就是Turn All  Layer Off就是打开图层和关闭图层。

其中,caption名字的变化是定义了一个Caption属性来修改。SubType值是通过在m_MenuMap.AddItem时根据第二个参数来定义。具体的细节我也不太懂,以后弄明白了再补充。

在这里在讲述一下IHOOKHelper接口:

IHookHelper 主要在用在自定义类型于AE带的的ICommand或ITool等,

1.实例化IHookHelper 对象:


IHookHelper m_hookHelper = new HookHelperClass(); 
m_hookHelper.Hook = this.axMapControl1.Object ;这样就可以把AxMapControl传递给其它要用到的地方。

2.通过IHookHelper,获取地图控件和主窗体:

IntPtr pHandle = new IntPtr (m_hookHelper.ActiveView.ScreenDisplay.hWnd);
axMapControl1 = System.Windows.Forms.Form.FromHandle(pHandle) as AxMapControl;//对这个地图控件对象操作,会直接反应到主窗体的地图控件上

Form. MainForm. = Form.FromHandle(pHandle).FindForm();//这里的主窗体对象之后运行时能起作用,MainForm. 不能直接访问到主窗体里的变量。

3.通过IHookHelper,获取IActiveView和IMap对象

再通过IHookHelper.ActiveView和IHookHelper.FocusMap属性来获取IActiveView和IMap对象,通过这两个接口进行更一步的操作.


4.通过IHookHelper,操作地图

IHookActions hookActions= m_hookHelper as IHookHelper;
获取IHookActions,再通过IHookActions进行Flash,Pan,ZoomTo操作.

HOOK实际是一个对象传出的自身的引用或者叫指针或者叫句柄。 
例如一个程序,加载一个dll内的对象时通过把Hook传递给要调用的对象,
这样dll内的对象就得到了应用程序传递给他的这个hook,
对象可以通过这个hook查看程序内部的结构。
实际实现时就是对象间传递指向自身的指针传递给另一个对象。

 

 

IHookHelper  m_hookHelper=new HookHelperClass();
m_hookHelper.Hook=axMapControl1.Object;
 //这样就获得了axMapControl1控件的一个引用
然后通过m_hookHelper.ActiveView可以获得原axMapControl1的ActiveView项,
用m_hookHelper.FocusMap可以获得IMap对象 



三、在Form1的Lord响应函数中初始化图层菜单,这一步在鼠标右键的响应函数中做初始化也一样。先后问题而已。
//右键菜单项的初始化
            m_MenuMap = new ESRI.ArcGIS.Controls.ToolbarMenuClass();
            m_MenuLayer = new ESRI.ArcGIS.Controls.ToolbarMenuClass();
            m_TocControl = (ITOCControl2)this.axTOCControl1.Object; 
            //添加自定义菜单项到TOCCOntrol的Map菜单中 
            //打开文档菜单
            m_MenuMap.AddItem(new OpenNewMapDocument(m_controlsSynchronizer), -1, 0, false, esriCommandStyles.esriCommandStyleIconAndText);
            //添加数据菜单
            m_MenuMap.AddItem(new ControlsAddDataCommandClass(), -1, 1, false, esriCommandStyles.esriCommandStyleIconAndText);
            //打开全部图层菜单
            m_MenuMap.AddItem(new LayerVisibility(), 1, 2, false, esriCommandStyles.esriCommandStyleTextOnly);
            //关闭全部图层菜单
            
            m_MenuMap.AddItem(new LayerVisibility(), 2, 3, false, esriCommandStyles.esriCommandStyleTextOnly);
            //以二级菜单的形式添加内置的“选择”菜单
            m_MenuMap.AddSubMenu("esriControls.ControlsFeatureSelectionMenu", 4, true);
            //以二级菜单的形式添加内置的“地图浏览”菜单
            m_MenuMap.AddSubMenu("esriControls.ControlsMapViewMenu", 5, true);


            //添加自定义菜单项到TOCCOntrol的图层菜单中
            m_MenuLayer = new ToolbarMenuClass();
            //添加“移除图层”菜单项
            m_MenuLayer.AddItem(new RemoveLayer(), -1, 0, false, esriCommandStyles.esriCommandStyleTextOnly);
            //添加“放大到整个图层”菜单项
            m_MenuLayer.AddItem(new ZoomToLayer(), -1, 1, true, esriCommandStyles.esriCommandStyleTextOnly);


            //设置菜单的Hook
            m_MenuLayer.SetHook(m_mapControl);
            m_MenuMap.SetHook(m_mapControl);
            //右键菜单项的初始化--end

在最后一步中设置菜单Hook的时候是对菜单中所有添加的项进行设置,当然也可以自己调用每个命令的Oncreat进行传递Hook。代码如下:

ICommand m_Command=new ControlsMapZoomInToolClass();//自带的一个放大功能的类

m_Command。OnCreate(m_mapControl.Object);

m_mapCiontrol.CurrentTool=(ITool)m_Command;//对于需要点击的命令响应OnClick()。


四、鼠标右键响应函数

   private void axTOCControl1_OnMouseDown(object sender, ITOCControlEvents_OnMouseDownEvent e)
        {
            //如果不是右键按下直接返回
            if (e.button != 2) return;


            esriTOCControlItem item = esriTOCControlItem.esriTOCControlItemNone;
            IBasicMap map = null;
            ILayer layer = null;
            object other = null;
            object index = null;


            //判断所选菜单的类型
            m_TocControl.HitTest(e.x, e.y, ref item, ref map, ref layer, ref other, ref index);
            

            //确定选定的菜单类型,Map或是图层菜单
            if (item == esriTOCControlItem.esriTOCControlItemMap)
                m_TocControl.SelectItem(map, null);
            else
                m_TocControl.SelectItem(layer, null);

            m_MenuLayer.SetHook(m_mapControl);
            m_MenuMap.SetHook(m_mapControl);
            //设置CustomProperty为layer (用于自定义的Layer命令)                   
            m_mapControl.CustomProperty = layer;

            
                //弹出右键菜单
                if (item == esriTOCControlItem.esriTOCControlItemMap)
                    m_MenuMap.PopupMenu(e.x, e.y, m_TocControl.hWnd);
            if (item == esriTOCControlItem.esriTOCControlItemLayer)
                m_MenuLayer.PopupMenu(e.x, e.y, m_TocControl.hWnd);
        }

      
    }

这里有一个不太明白的地方:

            //设置CustomProperty为layer (用于自定义的Layer命令)                  
            m_mapControl.CustomProperty = layer;

这一句不太懂。

运行结果:



附录:axTOCControl.HitTest方法介绍

public void HitTest ( int X, int Y, ref esriTOCControlItem ItemType, ref IBasicMap BasicMap, ref ILayer Layer, ref object Unk, ref object Data );

各参数的含义如下:

X,Y :鼠标点击的坐标;

ITemType: esriTOCControlItem枚举常量

BasicMap:绑定MapControl的IBasicMap接口

Layer:被点击的图层

Unk:TOCControl的LegendGroup对象

Data:LegendClass在LegendGroup中的Index。

esriTOCControlItem枚举常量用于描述TocControl上的Item的类型,其定义如下:

esriTOCControlItemNone      0      没有对象

esriTOCControlItemMap        1      Map对象

esriTOCControlItemLayer      2      Layer对象

esriTOCControlItemHeading      3      对象的标题

esriTOCControlItemLegendClass   4      LegendClass对象

----------------------------------------------------------end---------------------------------------------------
  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值