ArcGis Classic COM Add-Ins插件开发的一般流程 C#
COM add-ins是我对这种开发方式的称呼,Esri的官方文档里称其为“Extending ArcObject”或者“Classic COM extensibility”,Esri所称的addins是指esriAddin加载项。esriAddin的安装包是扩展名为“.esriAddin”的压缩文件,而本文所讲述的Com add-ins的安装文件只是一个dll,可以选择是否生成.tlb(Type Library)文件以通过在ArcGis的桌面程序中加载.tlb文件实现插件的加载,不过这种加载方式有时会存在问题,具体的会在后续的“安装与卸载”博文中作出说明。
COM add-ins是一种不同于esriAddin的开发方式,该种开发方式较后者对com组件的操作更直接,而且更全面。参考官方链接。
add-ins应该称为“加载项”才对,plug in翻译成“插件”,混起来都叫“插件”。
本例说明
开发目的:在ArcMap添加一个工具条ToolBar,上添加一个按钮Command,点击按钮,弹窗 say hello。
ArcGis版本:10.1
VisualStudio版本:2010
开发环境(IDE)的搭建
开发使用的Visual Studio版本最好与安装的ArcGis版本一致,避免不必要的麻烦(VS可以多版本并存的),本实例开发ArcMap 10.1的工具条插件,适配VS2010版本。先安装VS2010,再安装与ArcGis同版本的ArcObjects SDK for .NET,然后就可以开始在VS开发插件了。
Let's code
一、创建一个解决方案
1、名为ArcGis Classic COM extensibility demo
2、模板选择ArcGis——Extending ArcObject——Class Library(ArcMap)

3、可以选择添加引用,也可以直接“Finish”,在创建解决方案之后添加。

4、创建“解决方案”后
在项目名称上右键——属性——生成,勾选“为COM互操作注册”,这样就可以在生成的时候自动注册Com组件并且生成.tlb文件用以加载插件到ArcGis。
在属性——调试——启动外部程序,添加ArcGis的路径。
一般在利用模板创建解决方案的时候以上已经自动设置。
5、默认项目里会生成一个class1.cs,可以直接删掉。后面用到的时候再添加“类库”。

二、添加一个Toolbar
1、在项目名上右键——添加——新建项,如下图,选择模板Base Toolbar,向导程序类型当然是ArcMap。


2、看一下模板里都自动添加了啥。
①这个类继承了BaseToolbar,以实现其方法、属性;
②自动生成了类的特性,GUID以标识该类,ProgId也用于标识该类,不过前者具有唯一性,COM组件注册时将GUID写入注册表。
[Guid("deb23831-5b2e-453c-b900-f12462b000fb")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("ArcGis_Classic_COM_extensibility_demo.ArcGISToolbar1")]
③从模板创建toolbar类时还创建了一个构造函数,重写了两个方法(属性)。
在构造函数中,
使用基类提供的AddItem方法将Command、Menu Command等添加到工具条(Toolbar),该方法提供了6个重载,可以根据需要选用,一般使用AddItem("ProgId")即可;
使用基类提供的BeginGroup方法创建一个分隔器,其在工具条上表现为分隔开不同类别功能(自己定义)的竖线。
在重写的两个方法中,
Caption返回string类型的标题,用以显示Toolbar的标题,这里我们命为"My First Toolbar",Name则是程序内部的标识。
public ArcGISToolbar1()
{
//构造函数,添加Command、Menu Command等至此,加载到工具条(Toolbar)
//AddItem("esriArcMapUI.ZoomInTool");
//BeginGroup(); //Separator
//AddItem("{FBF8C3FB-0480-11D2-8D21-080009EE4E51}", 1);
//AddItem(new Guid("FBF8C3FB-0480-11D2-8D21-080009EE4E51"), 2);
}
public override string Caption
{
get
{
// bar caption
return "My First Toolbar";
}
}
public override string Name
{
get
{
// bar ID
return "ArcGISToolbar1";
}
}
④最后看一下COM组件注册函数,没兴趣可以跳过。
ArcGISCategoryRegistration与ArcGISCategoryUnregistration两个方法在COM组件注册或者反注册时分别会被RegisterFunction、UnregisterFunction两个方法调用。
#region COM Registration Function(s)
[ComRegisterFunction()]
[ComVisible(false)]
static void RegisterFunction(Type registerType)
{
ArcGISCategoryRegistration(registerType);
}
[ComUnregisterFunction()]
[ComVisible(false)]
static void UnregisterFunction(Type registerType)
{
ArcGISCategoryUnregistration(registerType);
} #region ArcGIS Component Category Registrar generated code
private static void ArcGISCategoryRegistration(Type registerType)
{
string regKey = string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}", registerType.GUID);
MxCommandBars.Register(regKey);
}
private static void ArcGISCategoryUnregistration(Type registerType)
{
string regKey = string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}", registerType.GUID);
MxCommandBars.Unregister(regKey);
}
#endregion
#endregion
RegisterFunction、UnregisterFunction两个方法是COM注册与反注册方法,执行COM组件注册时调用。
ArcGISCategoryRegistration与ArcGISCategoryUnregistration两个方法分别调用MxCommandBars类提供的Register与Unregister方法实现注册与反注册。
而MxCommandBars等的组件注册的类由ESRI.ArcGIS.ADF.CATIDs这个命名空间提供,该命名空间在ESRI.ArcGIS.ADF.dll中,可以在C:\Program Files (x86)\ArcGIS\DeveloperKit10.1\DotNet\ESRI.ArcGIS.ADF.dll找到该dll,具体路径可能因ArcObjects SDK for .NET安装位置与系统位数而异。
反编译一下dll,跟踪一下就可以看看注册的时候发生啥了?
看看注册表你会惊奇地发现插件注册时并没有按照ESRI.ArcGIS.ADF.CATIDs.CatReg的方法干活儿。自10.0开始ESri改变了以往的把COM组件类别部分注册信息写进注册表的注册方法,采用了自家的ESRIRegAsm.exe对dll进行注册,将部分信息写入注册表,搭配一个xml文档保存注册信息。
对注册表写入的内容与位置可以通过插件注册前后的注册表快照分析得出。
XML配置文档的被包裹在一个.ecfg格式的文档中,而这个.ecfg文档实质是一个“匿名的”压缩文件,嗯,又是“压缩文件”,看来Esri的大神喜欢把东西塞进压缩文件以创造新格式……
.ecfg文档在~:\Program Files\Common Files\ArcGIS\Desktop10.0\Configuration\CATID路径下
至于ESRIRegAsm.exe对dll进行注册时干了什么样神奇的操作,不得而知,俺没有找到相关支持材料。
using System;
namespace ESRI.ArcGIS.ADF.CATIDs
{
/// <summary>Registers or unregisters a class to the MxCommandBars component category.</summary>
public class MxCommandBars : CatReg
{
/// <summary>Registers a class to the MxCommandBars component category.</summary>
/// <param name="CLSID">The CLSID of the class to be registered.</param>
public static void Register(string CLSID)
{
CatReg.Reg(CLSID, "{B56A7C4A-83D4-11D2-A2E9-080009B6F22B}");
} /// <summary>Unregisters a class from the MxCommandBars component category.</summary>
/// <param name="CLSID">The CLSID of the class to be unregistered.</param>
public static void Unregister(string CLSID)
{
CatReg.Unreg(CLSID, "{B56A7C4A-83D4-11D2-A2E9-080009B6F22B}");
}
}
}
三、添加一个Command
同样是添加“新建项”,这次模板选BaseCommand,向导程序类型ArcMap。

1、看一按下构造函数
上边是一堆按钮的属性设置代码,一般地可以只设置m_caption与m_toolTip,后者提供鼠标悬浮于按钮之上显示的提示文字。
try……catch……语句块里是对按钮图标的定义,如果注释掉,按钮显示m_caption的内容。
可以替换自动生成的图片为自己需要的图片,注意格式;另外,俺提供一种更为简单的方法,在资源文件中添加图标,直接使用下面method2的方式使用即可。
public Command1()
{
base.m_category = ""; //localizable text
base.m_caption = "SayHello"; //localizable text
base.m_message = ""; //localizable text
base.m_toolTip = "show a messagebox"; //localizable text
base.m_name = ""; //unique id, non-localizable (e.g. "MyCategory_ArcMapCommand")
try
{
//method1:
string bitmapResourceName = GetType().Name + ".bmp";
base.m_bitmap = new Bitmap(GetType(), bitmapResourceName);
//method2:把图标塞进资源文件,然后直接使用
// base.m_bitmap = Properties.Resources.cmd_ExportExcel;
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message, "Invalid Bitmap");
}
}
2、创建一个WinFrom
为了贴近实际编程需求,这里创造难度,在点击按钮时弹出WinFrom,WinFrom上加一个button按钮,点击在ArcMap的Statusbar上留一行文字。

引入两个命名空间
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Framework
在窗体初始化时传入hookHeper,在点击button时获取当前宿主application,在Statusbar上写字
using System;
using System.Windows.Forms;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Framework; namespace ArcGis_Classic_COM_extensibility_demo
{
public partial class Form1 : Form
{
IHookHelper m_hookHelper;
IApplication m_application;
public Form1(IHookHelper hookHeper)
{
InitializeComponent();
m_hookHelper = new HookHelperClass();
m_hookHelper = hookHeper;
}
private void button1_Click(object sender, EventArgs e)
{
m_application= m_hookHelper.Hook as IApplication;
m_application.StatusBar.set_Message(,"I am good,I am great,I am wonderful.");
}
}
}
3、回到Command1
重写OnCreate方法,在command按钮初始化的时候实例化IHookHelper类型。
重写OnClick方法,在点击的时候实例化Form1,并弹窗。
IHookHelper m_hookHelper;
public override void OnCreate(object hook)
{
if (hook == null)
return;
m_hookHelper = new HookHelperClass();
m_hookHelper.Hook = hook;
}
public override void OnClick()
{
//Form实例化时传入IHookHelper 参数
Form1 f = new Form1(m_hookHelper);
f.Show();
}
④ 去ToolBar1添加按钮ProgID
AddItem("ArcGis_Classic_COM_extensibility_demo.Command1");
四、生成一下
在ArcMap就可以看到效果了。

插件咋加载到ArcMap的,还有什么其他方法加载,怎么卸载?戳 ArcGis Classic COM Add-Ins插件dll的安装与卸载
ArcGis Classic COM Add-Ins插件开发的一般流程 C#的更多相关文章
- ArcGis Classic COM Add-Ins插件dll的安装与卸载
本文是去年<ArcGis Classic COM Add-Ins插件开发的一般流程 C#>一文(以下称“开发流程”)的后续.“开发流程”中写到会有“安装与卸载”系列的文章,今天把它补上. ...
- 在Revit中如何显示附件模块(Add Ins) 这个命令页?zz
分类: 概念说明 Revit Revit界面编程 Revit 二次开发入门2013-08-22 13:58 1395人阅读 评论(9) 收藏 举报 在windows 7 32-bit OS 上装了 ...
- arcgis python arcpy add data script添加数据脚本
arcgis python arcpy add data script添加数据脚本mxd = arcpy.mapping.MapDocument("CURRENT")... df ...
- ArcGIS ArcMap “ Add Data” 打开后,一直卡死,无内容
打开ArcMap能打开,Add Data 或打开mxd就出Runtime Error对话框.打开ArcCatlog或者ArcGlobe出现Runtime Error对话框Runtime Error!P ...
- ArcGIS for Android_离在线一体化核心技术基本流程
核心思想: a.数据首先存储于ArcSDE中,要素添加GlobleID,图层数据启用数据归档或开启版本化.b.然后将ArcSDE数据库托管于ArcGIS for Server作为数据存储.c.在Arc ...
- Add In 简介(主要翻译于ESRI官方文档)
为ArcGIS桌面端建立Add In插件 平时以工作为主,有空时翻译一些文档,顺便练习英文,这个是因为用Add In来学习一下. 主要包括: 关于Add In 什么时候使用Add In Python ...
- Portal for ArcGIS 资源承载数据类型
在Portal中数据主要分为两大类:Web内容与桌面内容.对于Web内容与桌面内容中的每个项目(item)又被具体分为maps,layers, styles, tools,applications,和 ...
- IntelliJ IDEA/Android Studio插件开发指南
前言 目前在为安卓手机QQ做自动化的相关工作,包括UI自动化,逻辑层自动化等.使用到的uiautomator等框架,需要在Android Studio进行编码工作. 其中很多工作如果做到插件化的话,可 ...
- ArcGIS 10.5新功能预览
ArcGIS for Server产品线被重命名为ArcGIS Enterprise. 带来更多丰富的时空GIS功能. 分析地理大数据 捕捉和分析实时传感器数据 快速地理影像分析 ArcGIS Ent ...
随机推荐
- 英语口语练习系列-C04-学校生活
连接到英语口语系列总分类 连接到上一章常用问句 登鹳雀楼 登鹳雀楼 唐代:王之涣 白日依山尽,黄河入海流. 欲穷千里目,更上一层楼. He is a fraternity brother. 他是兄弟会 ...
- Configuring Apache Kafka for Performance and Resource Management
Apache Kafka is optimized for small messages. According to benchmarks, the best performance occurs w ...
- rm: cannot remove ‘overlay/’: Device or resource busy
umount /var/lib/docker/overlay #取消挂载就可以啦 rm -rf overlay/
- Redhat7.3更换CentOS7 yum源
Redhat yum源是收费的,没有注册的Redhat机器是不能使用yum源的. 1.当前系统环境: 系统版本:Red Hat Enterprise Linux Server release 7.3 ...
- Linux运维期中架构(50台集群)
一.期中架构 二.期中架构-前端部分 三.第三阶段作业-期中架构
- React Router路由传参方式总结
首先我们要知道一个前提,路由传递的参数我们可以通过props里面的属性来获取.只要组件是被<Router>组件的<component>定义和指派的,这个组件自然就有了props ...
- 苹果手机连接Wifi认证机制
Wifi状态保持方法和nas设备 https://patents.google.com/patent/CN106793171A/zh 基于ios终端的离线wifi热点认证方法和认证系统 https:/ ...
- SpringBoot前端模板
Springboot支持thymeleaf.freemarker.JSP,但是官方不建议使用JSP,因为有些功能会受限制,这里介绍thymeleaf和freemarker. 一.thymeleaf模板 ...
- git 入门(转)
1. good https://github.com/521xueweihan/git-tips Git的奇技淫巧 2.如果之前未使用过 Git,可以学习 Git 小白教程入门 3.思维导图
- Spring Boot JPA Entity Jackson序列化触发懒加载的解决方案
Spring Jpa这项技术在Spring 开发中经常用到. 今天在做项目用到了Entity的关联懒加载,但是在返回Json的时候,不管关联数据有没有被加载,都会触发数据序列化,而如果关联关系没有被加 ...