• ICommand 用法


    原文地址:https://www.douban.com/note/153701872/

    向分享知识致谢!

    ------------------------------    正文  ----------------------------------------------------

    ICommand 用法
    在ArcEngine类库中有大量的Command控件用来与地图控件进行操作和交互。比如有一系列的地图浏览控件、地图查询控件、图斑选取控件、编辑控件来与MapControl和PageLayoutControl进行交互。这些控件被包含在ESRI.ArcGIS.Controls.dll类库中,位于ESRI.ArcGIS.Controls命名空间下。
    这些内置的Command控件可以单独实例化来使用,也可以被安置在一个AxToolbarControl工具栏控件中,继而被存放在一个CommandPool池中以备调用。下面对这两种方式分别加以说明:
    第一种使用方式是实例化一个Command对象并显式地运行它:
    ICommand command = new ControlsOpenDocCommandClass();
    command.OnCreate(m_mapControl.Object);
    command.OnClick();
    其中ControlsOpenDocCommandClass就是一个Command控件,通过调用它的OnCreate方法传递给它需要交互的MapControl,然后调用它的OnClick方法就可以运行。上面的例子会激活一个打开地图文档的对话框。
    另一种方法是更加常用的方法。
    由于每个Command对象都是一个COM组件,所以ESRI.ArcGIS.Controls下的各个类只是对底层的COM对象的一种封装。由于是COM对象,所以每一个Command对象都有自己的CLSID和ProgID,并在安装Engine Runtime的时候被注册了,你可以在注册表的HKEY_LOCAL_MACHINESOFTWAREClassesCLSID找到这些Command的注册信息,如果要查找所有Command的信息,请访问[url=http://edndoc.esri.com/arcobjects/9.2/net/b9a335a2-f653-44a1-8961-89051f2e958f.htm][size=3][color=#3468a4]Built-in commands[/color][/size][/url]。由于是COM组件,在实例化它的过程中,.net需要实例化一个Runtime Callable Wrapper(RCW)对象,来代理对COM组件的调用。
    由于大部分对地图控件的操作都直接或间接的来自于工具栏,比如点击工具栏上面的放大、缩小、全图按钮。那么实际上我们的绝大部分Command对象都可以被寄放到这个工具栏之中。方法非常简单:
    axToolbarControl1.AddItem("esriControls.ControlsMapZoomInTool");
    此处使用的esriControls.ControlsMapZoomInTool就是ControlsMapZoomInToolClass类所指向的COM组件的ProgID,需要所有这些Command的信息时,你应该到[url=http://edndoc.esri.com/arcobjects/9.2/net/b9a335a2-f653-44a1-8961-89051f2e958f.htm][size=3][color=#3468a4]Built-in commands[/color][/size][/url]这个页面下查找,或在你的Engine帮助文档中ms-help://ESRI.EDNv9.2/NET_Engine/b9a335a2-f653-44a1-8961-89051f2e958f.htm的位置。
    通过AddItem添加到工具栏中的Command控件使用非常方便,添加了它以后你就再不用操心进一步的处理它与地图控件的交互了。Engine内部是怎么做到这一点的呢,记得我们在第一种方法中实例化一个Command控件时调用的OnCreate方法吗,当时我们传递给它一个MapControl来告诉它需要控制哪一个地图控件。而通过axToolbarControl1.AddItem添加的控件,由于ToolbarControl将这个控件放到自己的控件池时,就已经调用了它的OnCreate方法,并传递给了它自己的BuddyControl作为控制对象,于是,一切都变得简单了。
    在实际开发项目中,我们往往不想暴露出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;
    }
       }
    }
    前面提到ToolbarControl内部维护一个Command池,在这个池中存放了所有已添加的Command对象,获取其中的Command可以通过CommandPool的get_Command方法,通过比较Command的名称,可以得到想要的Command对象。这个名称可不同于ProgID,它是另一个用来标识Command控件的字符串,具体的请在[url=http://edndoc.esri.com/arcobjects/9.2/net/b9a335a2-f653-44a1-8961-89051f2e958f.htm][size=3][color=#3468a4]Built-in commands[/color][/size][/url]上查找(第一列),比如我们之前添加的ZoomInTool控件,它的ProgID是esriControls.ControlsMapZoomInTool,它的Name是ControlToolsMapNavigation_ZoomIn。
    请注意这一行:
    m_Map.CurrentTool = _command as ITool;
    当Command对象处理的不只是打开地图,显示全图这类没有与地图交互的功能时,简单的使用OnClick即可,但是当需要的是拖动鼠标控制缩放,空间查询这类必须与地图进行交互的动作时,就必须设置MapControl的CurrentTool属性。
    通过上面介绍的方法,就可以不仅利用Toolbar控件管理Command功能,又可以提供丰富的UI,保证表现层的灵活性。
    内置的一系列Command控件可以满足我们很多的功能需求,但是仍有稍显不足的时候,比如Identify控件的全英文界面,会使有些用户抓狂。这时,我们可以通过自己开发Command控件来扩展出我们需要的功能,并可以像内置Command一样的使用。 前面提到了如何灵活地使用ArcEngine内置的Command控件,如果这些控件已经满足你的功能需求,就尽量使用它们,因为ArcEngine的开发一旦开始自己coding,往往遇到大量的代码量和性能问题。而ArcEgnine的SDK提供了很多减轻开发人员负担的模板、代码段、示例等等。下面我们对Command控件进行的扩展就利用了SDK提供的模板。
    由于Command对象封装了太多的信息,往往使用很方法,进行扩展却不易。比如内置的Identify控件,你只需要在工具栏中添加它就可以了:
    axToolbarControl1.AddItem("esriControls.ControlsMapIdentifyTool");
    它的功能极其完善,到与ArcDesktop提供的Identify工具几乎一样。但是我们想自定义弹出的对话框,省掉一些功能,把界面中文化,对不起,No door~。于是我们只好硬着头皮自己开发Identify功能,还有诸如EditingToolbar,MeasureTool这些控件都存在这样的烦恼。开发它们的难度是很大的,但是利用SDK提供的模板还是可以扫清基本思路上的障碍,并且开发出来以后可以在不同项目中重用。
    思路是这样,要使自己开发的Command控件能够像内置控件那样方便使用,你需要将你的Command类实现ICommand接口,如果进一步,这个Command会持久地与MapControl交互,你还需要实现ITool接口。比这高明一点的方法是继承自BaseCommand或BaseTool抽象类。这样需要手工编写实现的代码更少。最高明的方法则是使用SDK提供的模板创建这样的Command控件。
    在项目中选择添加新项,选择ArcGIS类别下的模板Base Command或Base Tool,如图:
    [img=670,382]http://www.cnblogs.com/images/cnblogs_com/renji/CommandWizard1.JPG[/img]
       点击确定之后会弹出一个对话框,让你选择要创建的Command适用的ArcGIS组件,选择MapControl or PageLayoutControl Command则可使Command用在普通的平面地图控件上。
    [img=353,359]http://www.cnblogs.com/images/cnblogs_com/renji/CommandWizard2.JPG[/img]
       最终生成的代码文件中,创建了一个类,继承自BaseCommand,提供了可供COM识别的一系列标签,实现了BaseCommand的必要方法OnCreate和OnClick。其中重要的部分说明如下:
    [Guid("4f2b2bfe-3f62-43ca-9ed3-36c8d233280c")]:使这个全局ID使此组件可以注册在你的电脑上; [ProgId("GTLControls.Command2")]:提供了这个COM组件的ProgId,这成为调用AddItem时传入的参数。 base.m_name:这个名称成为你在查找Command时进行比较的字符串名称。 OnCreate:方法中传递的参数hook成为绑定到这个Command控件的交互对象,被保存在一个IHookHelper成员变量中,通过该成员的Hook属性即可获得对交互对象(往往是MapControl的弱引用)。 同时被创建的还有一个bmp图片,是被添加到工具栏时显示的按钮图片,默认是一个傻傻的兔子。
    你需要实现的逻辑往往被放置在OnClick方法中。通过观察其中的TODO注释你可以找到在哪里开始编写自己的代码。
    在此没有必要对一个具体的Command对象如何实现进行更详细的说明,但要使一个自己开发的Command正常工作还是需要注意以下几点:
    1、这个Command必须位于一个Library项目中,当在一个exe项目中创建这样一个Command对象会无法使用,或者是我还没找到正确的办法。
    2、这个Library项目的属性需要勾选为COM Interop注册选项,在生成选项卡下。
    3、不要忘记在使用它的项目中添加对这个Library项目的引用。[img=1,1]http://imgcache.qq.com/ac/b.gif[/img]
    http://apps.hi.baidu.com/share/detail/861726

    ------------------------------------------------------------------------------------------------------------------------------------

    转载地址:http://blog.csdn.net/shiquanqq/article/details/41846835

    控件被包含在ESRI.ArcGIS.Controls.dll类库中,位于ESRI.ArcGIS.Controls命名空间下,详见ArcEngine帮助文档: ms-help://ESRI.EDNv9.3/NET_Engine/b9a335a2-f653-44a1-8961-89051f2e958f.htm

    1、ITool是异步执行,而ICommand是同步执行

    2、实现方法自然也有区别

    [csharp] view plain copy
     
     1 ICommand command = new ControlsOpenDocCommandClass();  
     3 command.OnCreate(m_mapControl.Object);  
     4 command.OnClick();  
     5 
     6 
     7 ICommand pCommand = new ESRI.ArcGIS.Controls.ControlsMapZoomInToolClass();  
     8 
     9 pCommand.OnCreate(axMapControl1.Object);  
    10 axMapControl1.CurrentTool = pCommand as ITool;

  • 相关阅读:
    数据--第53课
    数据--第52课
    数据--第51课
    标准模板库中的优先队列(priority_queue)
    进程的定义
    进程的基本概念
    循环不变式
    插入排序
    模板声明
    标准模板库中的队列(queue)
  • 原文地址:https://www.cnblogs.com/marvelousone/p/7417963.html
Copyright © 2020-2023  润新知