ArcMap扩展开发实习指导书.docx
《ArcMap扩展开发实习指导书.docx》由会员分享,可在线阅读,更多相关《ArcMap扩展开发实习指导书.docx(16页珍藏版)》请在冰豆网上搜索。
ArcMap扩展开发实习指导书
ArcMap拓展开发实习指导书
1、以ArcGISC#插件开发
使用C#和ArcObject10.1开发ArcGIS插件,开发的电脑上必须安装ArcGIS基础平台,同时必须安装支持.NET的开发库。
在这里我们使用VisualStudio2010作为开发环境。
开发步骤如下:
1、启动VisualStudio2010,创建VisualC#的类库项目,名称为BufferExSolution,如图2_1所示。
2_1创建项目
2、在解决方案资源管理器中,选择BufferExSolution项目,右键添加新建项目,选在ArcGIS模板下的BaseCommand模板,将名称设置为BufferEx,如图2_2所示,点击“添加”按钮,出现如图2_3所示的选择项,选择第二项,其意义为在ArcMap、MapControl或者PageLayoutControl中都可以使用新建的插件。
2_2
3、添加名为“BufferDlg”的Windows窗体,如图2_4所示。
这样在资源管理器中就出现了
图2_4
4、为BufferDlg窗体添加控件,控件布局如图2_5所示。
控件属性如表2_1所示。
图2_5
表2_1
控件类型
Name属性
Text属性
其它属性
Label
lblChoseLayer
选择图层
Label
lblRadio
缓冲区半径
Label
lblOutPath
输出路径
Combox
cboLayers
TextBox
txtBufferDistance
Text=0.1
Combox
cboUnits
Items=Unknown
Inches
Points
Feet
Yards
Miles
NauticalMiles
Millimeters
Centimeters
Meters
Kilometers
DecimalDegrees
Decimeters
TextBox
txtOutputPath
Enable=false
Button
btnOutputLayer
…
Button
btnBuffer
输出
GroupBox
gpbTips
提示
TextBox
txtMessages
MultiLine
Button
btnCancel
关闭
5、为修改BufferCmd类,首先修改其构造函数:
publicBufferCmd()
{
base.m_category="缓冲区创建工具";
base.m_caption="缓冲区创建";
base.m_message="ThisshouldworkinArcMap/MapControl/PageLayoutControl";
base.m_toolTip="缓冲区创建";
base.m_name="BufferCmd";
try
{
stringbitmapResourceName=GetType().Name+".bmp";
base.m_bitmap=newBitmap(GetType(),bitmapResourceName);
}
catch(Exceptionex)
{
System.Diagnostics.Trace.WriteLine(ex.Message,"InvalidBitmap");
}
}
6、为OnClick函数添加如下代码:
publicoverridevoidOnClick()
{
if(null==m_hookHelper)
return;
if(m_hookHelper.FocusMap.LayerCount>0)
{
BufferDlgbufferDlg=newBufferDlg(m_hookHelper);
bufferDlg.Show();
}
}
其中,IHookHelperm_hookHelper主要在用在自定义类型于AO/AE带的的ICommand或ITool等。
在BufferCmd类中,OnCreate函数将object类型的参数hook传递给m_hookHelper,而m_hookHelper又可以作为参数在OnClick函数中传递给BufferDlg类,这样就实现了ArcMap中数据向插件传递,从而实现插件对宿主程序中数据的操作、拓展了宿主程序的功能。
OnCreate函数的代码如下:
publicoverridevoidOnCreate(objecthook)
{
if(hook==null)
return;
try
{
m_hookHelper=newHookHelperClass();
m_hookHelper.Hook=hook;
if(m_hookHelper.ActiveView==null)
m_hookHelper=null;
}
catch
{
m_hookHelper=null;
}
if(m_hookHelper==null)
base.m_enabled=false;
else
base.m_enabled=true;
}
OnClick函数的作用就是:
当ArcMap中加载了该插件,只要点击该插件的按钮,则就执行OnClick函数,也就是将BufferDlg窗体调出来。
下面,我们将为BufferDlg窗体添加控件响应事件。
7、修改BufferDlg类的构造函数,使构造函数有一个类型为IHookHelper的参数,实现从BufferCmd类中接收宿主程序的数据。
publicBufferDlg(IHookHelperhookHelper)
{
InitializeComponent();
m_hookHelper=hookHelper;
}
通过IHookHelper类型的实例将宿主程序的对象传到插件中的机制如下:
IHookHelperm_hookHelper=newHookHelperClass();
m_hookHelper.Hook=this.axMapControl1.Object;这样就可以把AxMapControl传递给其它要用到的地方,再通过IHookHelper.ActiveView和IHookHelper.FocusMap属性来获取IActiveView和IMap对象,通过这两个接口进行更一步的操作。
8、完善BufferDlg类,为其添加相应的字段,同时依次为表2_1中列出的控件添加相应的事件响应,BufferDlg类实现代码如下:
publicpartialclassBufferDlg:
Form
{
//委托机制,目的是在.Net环境中使用Win32函数
[DllImport("user32.dll")]
privatestaticexternintPostMessage(IntPtrwnd,
uintMsg,
IntPtrwParam,
IntPtrlParam);
privateIHookHelperm_hookHelper=null;
privateconstuintWM_VSCROLL=0x0115;
privateconstuintSB_BOTTOM=7;
publicBufferDlg(IHookHelperhookHelper)
{
InitializeComponent();
m_hookHelper=hookHelper;
}
privatevoidbufferDlg_Load(objectsender,EventArgse)
{
if(null==m_hookHelper||null==m_hookHelper.Hook||0==m_hookHelper.FocusMap.LayerCount)
return;
//将ArcMap中的图层名称显示到combox中
IEnumLayerlayers=GetLayers();
layers.Reset();
ILayerlayer=null;
while((layer=layers.Next())!
=null)
{
cboLayers.Items.Add(layer.Name);
}
//设置默认图层
if(cboLayers.Items.Count>0)
cboLayers.SelectedIndex=0;
stringtempDir=System.IO.Path.GetTempPath();
txtOutputPath.Text=System.IO.Path.Combine(tempDir,((string)cboLayers.SelectedItem+"_buffer.shp"));
//设置默认的缓冲半径单位
intunits=Convert.ToInt32(m_hookHelper.FocusMap.MapUnits);
cboUnits.SelectedIndex=units;
}
privatevoidbtnOutputLayer_Click(objectsender,EventArgse)
{
//设置输出shp文件路径
SaveFileDialogsaveDlg=newSaveFileDialog();
saveDlg.CheckPathExists=true;
saveDlg.Filter="Shapefile(*.shp)|*.shp";
saveDlg.OverwritePrompt=true;
saveDlg.Title="输出图层";
saveDlg.RestoreDirectory=true;
saveDlg.FileName=(string)cboLayers.SelectedItem+"_buffer.shp";
DialogResultdr=saveDlg.ShowDialog();
if(dr==DialogResult.OK)
txtOutputPath.Text=saveDlg.FileName;
}
privatevoidbtnBuffer_Click(objectsender,EventArgse)
{
doublebufferDistance;
//获取缓冲区半径
double.TryParse(txtBufferDistance.Text,outbufferDistance);
if(0.0==bufferDistance)
{
MessageBox.Show("缓冲区半径不合法!
");
return;
}
//检查输出路径合法性
if(!
System.IO.Directory.Exists(System.IO.Path.GetDirectoryName(txtOutputPath.Text))||
".shp"!
=System.IO.Path.GetExtension(txtOutputPath.Text))
{
MessageBox.Show("输出文件名不正确!
");
return;
}
//检测宿主程序(ArcMap)中是否存在图层
if(m_hookHelper.FocusMap.LayerCount==0)
return;
//从ArcMap中获得图层
IFeatureLayerlayer=GetFeatureLayer((string)cboLayers.SelectedItem);
if(null==layer)
{
txtMessages.Text+="Layer"+(string)cboLayers.SelectedItem+"不能被找到!
\r\n";
return;
}
//设置消息框有滚动条
ScrollToBottom();
txtMessages.Text+="\r\n分析开始,这可能需要几分钟时间,请稍候..\r\n";
txtMessages.Update();
//获得geoprocessor实例
Geoprocessorgp=newGeoprocessor();
gp.OverwriteOutput=true;
//创建缓冲区生成工具
ESRI.ArcGIS.AnalysisTools.Bufferbuffer=newESRI.ArcGIS.AnalysisTools.Buffer(layer,txtOutputPath.Text,Convert.ToString(bufferDistance)+""+(string)cboUnits.SelectedItem);
buffer.dissolve_option="ALL";//这个要设成ALL,否则相交部分不会融合
//buffer.line_side="FULL";//默认是"FULL",最好不要改否则出错
//buffer.line_end_type="ROUND";//默认是"ROUND",最好不要改否则出错
//执行缓冲区生成工具
IGeoProcessorResultresults=null;
try
{
results=(IGeoProcessorResult)gp.Execute(buffer,null);
}
catch(Exceptionex)
{
txtMessages.Text+="Failedtobufferlayer:
"+layer.Name+"\r\n";
}
if(results!
=null&&results.Status!
=esriJobStatus.esriJobSucceeded)
{
txtMessages.Text+="Failedtobufferlayer:
"+layer.Name+"\r\n";
}
ScrollToBottom();
txtMessages.Text+="\r\n分析完成.\r\n";
txtMessages.Text+="----------------------------------------\r\n";
ScrollToBottom();
}
privatestringReturnMessages(Geoprocessorgp)
{
StringBuildersb=newStringBuilder();
if(gp.MessageCount>0)
{
for(intCount=0;Count<=gp.MessageCount-1;Count++)
{
System.Diagnostics.Trace.WriteLine(gp.GetMessage(Count));
sb.AppendFormat("{0}\n",gp.GetMessage(Count));
}
}
returnsb.ToString();
}
///
///根据名称获取图层对象
///
///
///
privateIFeatureLayerGetFeatureLayer(stringlayerName)
{
//从ArcMap中获得layers
IEnumLayerlayers=GetLayers();
layers.Reset();
ILayerlayer=null;
while((layer=layers.Next())!
=null)
{
if(layer.Name==layerName)
returnlayerasIFeatureLayer;
}
returnnull;
}
privateIEnumLayerGetLayers()
{
UIDuid=newUIDClass();
uid.Value="{40A9E885-5533-11d0-98BE-00805F7CED21}";
IEnumLayerlayers=m_hookHelper.FocusMap.get_Layers(uid,true);
returnlayers;
}
privatevoidScrollToBottom()
{
PostMessage((IntPtr)txtMessages.Handle,WM_VSCROLL,(IntPtr)SB_BOTTOM,(IntPtr)IntPtr.Zero);
}
privatevoidbtnCancel_Click(objectsender,EventArgse)
{
this.Close();
}
}
9、编译运行程序,提示缺少引用。
按照提示添加相应的引用。
重新编译运行,则程序生成一个名为BufferExSolution.dll和一个名为BufferExSolution.tlb的文件。
这两个程序就是插件程序,在ArcMap中可以直接使用。
在ArcMap中使用上面生成的插件的步骤如下:
1、启动ArcMap程序,通过“Tools”/“Customize”菜单打开Customize对话框,如图2_6所示。
图2_6
2、在Toolbars页面点击“New”按钮,新建一个名为Buffer_Create的工具按钮,如图2_7所示。
图2_7
3、在Commands页面点击“Addfromfile”按钮,选择创建的插件文件,如图2_8所示。
图2_8
点击“打开”,则插件就被安装到了宿主程序,也即ArcMap程序中。
如图2_9所示。
图2_9
4、将如图2_9所示的“缓冲区分析”拖拽到第二部所创建的工具按钮上,关闭Customize对话框,调整Buffer_Create工具按钮的位置。
至此,该插件就可以使用了。
图2_10是插件运行实例。
图2_10
上面这个例子仅仅只是给读者演示了C#开发GIS插件的可行性例子,给读者一个思路。
C#是语言,要想很好的开发ArcGIS插件,必须认真学习ArcObject/ArcEngine,建议读者阅读相关书籍。