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 ...
随机推荐
- jvisualvm 连接 jstatd 远程监控 jvm 或 Visual GC提示"不受此JVM支持“
Visual GC提示"不受此JVM支持",可以使用此方法解决. 一.添加配置文件 jstatd.all.policy [root@localhost /]# cd /usr/lo ...
- Python操作MySQL:pymysql模块
连接MySQL有两个模块:mysqldb和pymysql,第一个在Python3.x上不能用,所以我们学pymysql import pymysql # 创建连接 conn = pymysql.con ...
- linux 本机内核模块
make -C /lib/modules/4.13.0-36-generic/build M=/$(pwd) modules 内核里只需要写obj-m:=hello.o
- day6-基础函数的学习(一)
今日份目录 1.函数的定义 2.函数的返回值 3.函数的参数 4.函数的局部变量与全局变量 5.名称空间与作用域 6.global与nonlocal 7.高阶函数 继续今日份总结!这个总结也晚了,哎, ...
- 如何将Bitcoin比特币区块链数据导入关系数据库
在接触了比特币和区块链后,我一直有一个想法,就是把所有比特币的区块链数据放入到关系数据库(比如SQL Server)中,然后当成一个数据仓库,做做比特币交易数据的各种分析.想法已经很久了,但是一直没有 ...
- 在C#/.NET应用程序开发中创建一个基于Topshelf的应用程序守护进程(服务)
本文首发于:码友网--一个专注.NET/.NET Core开发的编程爱好者社区. 文章目录 C#/.NET基于Topshelf创建Windows服务的系列文章目录: C#/.NET基于Topshelf ...
- 《Linux/UNIX系统编程手册》第63章 IO多路复用、信号驱动IO以及epoll
关键词:fasync_helper.kill_async.sigsuspend.sigaction.fcntl.F_SETOWN_EX.F_SETSIG.select().poll().poll_wa ...
- Java面试准备之探究源码
摘要:之前虽然对集合框架一些知识点作了总结,但是想想面试可能会问源码,于是又大致研究了一下集合框架的一些实现类的源码,在此整理一下. 一.集合框架 二.深究实现类 1.ArrayList源码实现 Ar ...
- 二十六、css3改变checkbox复选框的样式
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 小程序蓝牙BLE——自动连接设备(手环)
了解小程序蓝牙API: /** *蓝牙API: * 1.初始化蓝牙(判断蓝牙是否可用):openBluetoothAdapter * 2.获取蓝牙设备状态(蓝牙是否打开):getBluetoothAd ...