ToolbarControl

来源:互联网 发布:单片机就业方向 编辑:程序博客网 时间:2024/05/21 14:41

导读

  ToolbarControl是一个装载地图操作命令和工具的控件,该类内部维护一个CommandPool命令池,在这个命令池中存放着所有已经添加的Command对象,获取其中的Command可以通过CommandPool的get_Command方法,通过比较Command的名称,可以得到想要的Command对象。

ToolbarControl与MapControl的关系

  前面已经提到ToolbarControl是一个装载“地图操作”命令和工具的控件,说明ToolbarControl必须和MapControl关联才有实际作用,因为ToolbarControl里面的每个功能最终都是控制地图的显示,而MapControl是用来最终显示地图的,所有地图的展现是在MapControl里面,而一些基本操作或命令如放大缩小平移什么的都在ToolbarControl里面。
  ToolbarControl与MapControl的关联实际上是把CommandPool命令池中的每个Command命令与MapControl做关联。具体实现看如下代码,先创建一个打开地图文档命令对象command,然后通过OnCreate方法把MapControl的实例对象引用axMapControl1传递过去,这样就完成了关联。调用onClick方法即可使用该命令。这个例子会激活一个打开地图文档的对话框。

ICommand command = new ControlsOpenDocCommandClass();command.OnCreate(this.axMapControl1.Object);command.OnClick();

Command的使用

  这里大家可能有个疑问,文章主题是ToolbarControl,为什么这里不说ToolbarControl的使用。我们需要明白ToolbarControl是一系列命令的装载类,它负责管理这些命令,我们要实现的功能一般都是如何创建一个新的命令,让他去操作地图。所以Command是核心,我们必须掌握Command的创建和使用。

1. 实例化一个Command对象
  上文中已经提到过,利用ArcEngine提供的Command类创建一个操作地图的命令,调用OnCreate方法让该命令和MapControl关联起来,最后调用OnClick方法让该命令可用。 

ICommand command = new ControlsOpenDocCommandClass();command.OnCreate(m_mapControl.Object);command.OnClick();

2. 利用COM对象加载Command命令
  由于每个Command对象都是一个COM组件,所以ESRI.ArcGIS.Controls下的各个类只是对底层的COM对象的一种封装。由于是COM对象,所以每一个Command对象都有自己的CLSID和ProgID,并在安装Engine Runtime的时候被注册了,你可以在注册表的HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\找到这些Command的注册信息,如果要查找所有Command信息。由于是COM组件,在实例化它的过程中,.net需要实例化一个Runtime Callable Wrapper(RCW)对象,来代理对COM组件的调用。
  因为大部分对地图控件的操作都直接或间接的来自于工具栏,比如点击工具栏上面的放大、缩小、全图按钮。那么实际上我们的绝大部分Command对象都可以被寄放到这个工具栏之中。方法非常简单:

axToolbarControl1.AddItem("esriControls.ControlsMapZoomInTool");

  此处使用的esriControls.ControlsMapZoomInTool就是ControlsMapZoomInToolClass类所指向的COM组件的ProgID,需要所有这些Command的信息时,你应该到Command信息。
  通过AddItem添加到工具栏中的Command控件使用非常方便,添加了它以后你就再不用操心进一步的处理它与地图控件的交互了。Engine内部是怎么做到这一点的呢,记得我们在第一种方法中实例化一个Command控件时调用的OnCreate方法吗,当时我们传递给它一个MapControl来告诉它需要控制哪一个地图控件。而通过axToolbarControl1.AddItem添加的控件,由于ToolbarControl将这个控件放到自己的控件池时,就已经调用了它的OnCreate方法,并传递给了它自己的BuddyControl作为控制对象,于是,一切都变得简单了。
  
3. 自定义Command命令
  在实际开发项目中,我们往往不想暴露出ArcEngine内置的ToolBar控件,而是给用户展示我们自己开发的工具栏控件。另一方面,我们也想使用这种简单的添加控件机制。如果做到呢,方法就是在设计阶段,仍然拖放一个ToolbarControl到窗体上,但是在属性中将它的Visible设置为false,这样就不会显示出来了,而我们可以往这个工具栏中添加大量的Command控件。这个隐藏的工具栏如何使用呢,请看下面这个函数:

 public void SetCurrentMapTool(string commandName)        {            //先重置地图当前工具            m_Map.CurrentTool = null;            for (int i = 0; i < m_toolbarControl.CommandPool.Count; i++)            {                _command = m_toolbarControl.CommandPool.get_Command(i);                if (_command.Name == commandName)                {                    m_Map.CurrentTool = _command as ITool;                    _command.OnClick();                    break;                }            }        }

  请注意这一行:
  m_Map.CurrentTool = _command as ITool;
  当Command对象只处理打开地图,显示全图这类没有与地图交互的功能时,简单的使用OnClick即可,但是当需要的是拖动鼠标控制缩放,空间查询这类必须与地图进行交互的动作时,就必须设置MapControl的CurrentTool属性。通过上面介绍的方法,就可以不仅利用Toolbar控件管理Command功能,又可以提供丰富的UI,保证表现层的灵活性。
  下面以添加打开文件的命令为例:首先在项目文件下添加一个类,选择ArcGIS-BascCommand。如下图:
这里写图片描述
第二部选择应用命令的应用类型,如图所示,这里选择ArcMap的地图操作命令。
这里写图片描述
  新类创建成功后,C#中会预先定义好一部分代码。开发人员需要自己重写OnCreate 和 OnClick 两种方法代码。其中OnCreate 中会自动定义hook,即钩子,用于传递控件的信息。而在OnClick函数中则需要写单击按钮控件时所触发的动作。本例是打开地图文档,代码如下:

 public OpenNewMapDocument(AxMapControl mainMapCtl)        {            //            // TODO: Define values for the public properties            //相关属性设置            base.m_category = "Generic"; //localizable text            base.m_caption = "Open";  //localizable text             base.m_message = "This should work in ArcMap/MapControl/PageLayoutControl";  //localizable text            base.m_toolTip = "Open";  //localizable text            base.m_name = "Generic_Open";   //unique id, non-localizable (e.g. "MyCategory_MyCommand")            try            {                //                // TODO: change bitmap name if necessary                //                string bitmapResourceName = GetType().Name + ".bmp";                base.m_bitmap = new Bitmap(GetType(), bitmapResourceName);            }            catch (Exception ex)            {                System.Diagnostics.Trace.WriteLine(ex.Message, "Invalid Bitmap");            }            //初始化            m_MainMapControl = mainMapCtl;        }

其中控件的名称在类的构造函数中设置。

// TODO: Define values for the public properties
//相关属性设置
base.m_category = “Generic”; //自定义控件类型
base.m_caption = “Open”; //自定义控件文字,本例子是将控件上的文字设置为OPen
base.m_message = “This should work in ArcMap/MapControl/PageLayoutControl”; //自定义控件的提示信息
base.m_toolTip = “Open”; //自定义鼠标停留的提示信息
base.m_name = “Generic_Open”; //自定义控件的名称(如 “MyCategory_MyCommand”)
由于加载地图文档需要axMapControl 对象,因此在构造函数的参数中传入项目中的mapControl,并将其赋值给类中定义的m_MainMapControl 。其需要在类中提前定义,如下:
AxMapControl m_MainMapControl = null; //作为全局变量
然后就是OnClick函数的代码:

public override void OnClick()         {             // TODO: Add OpenNewMapDocument.OnClick implementation             OpenFileDialog dlg = new OpenFileDialog();             dlg.Filter = "Map Documents (*.mxd)|*.mxd";             dlg.Multiselect = false;             dlg.Title = "Open Map Document";             if (dlg.ShowDialog() == DialogResult.OK)             {                 string docName = dlg.FileName;                 IMapDocument mapDoc = new MapDocumentClass();                 if (mapDoc.get_IsPresent(docName) && !mapDoc.get_IsPasswordProtected(docName))                 {                     mapDoc.Open(docName, string.Empty);                     IMap map = mapDoc.get_Map(0);                   //  m_controlsSynchronizer.ReplaceMap(map);                     m_MainMapControl.Map = map;                     mapDoc.Close();                 }             }         }  

完成以后需要在项目的load函数中加载该类,因此在form1的load函数中加入如下代码:

// 添加打开命令按钮到工具条  OpenNewMapDocument openMapDoc = new OpenNewMapDocument(mainMapControl);  axToolbarControl1.AddItem(openMapDoc, -1, 0, false, -1, esriCommandStyles.esriCommandStyleIconAndText);  

就是把命令添加到工具条,其中esriCommandStyles.esriCommandStyleIconAndText 是定义控件的样式,该形式是Icon加文字。还可以选择只有位图或只有文字等不同样式。其中位图是新建类时自动创建的一个位图,不需要再自己导入位图。