阅读:1745回复:0
在vb.net环境下开发ArcMap 定制组件,有点疑问!!
<P>想在vb.net环境下开发ArcMap 定制组件,但是却始终不能成功,加载生成的dll的时候总是显示:can't load type library from specified file. 我知道这个原因是因为没有转化为COM ,但是我的代码中明明已经写了的呀</P>
<P>代码见下面:</P> <P>组件功能:放大视图一倍。</P> <H4>2.1 创建一个新的类库</H4> <P><FONT size=+0>1) </FONT>打开<FONT size=+0>Visual Studio .NET</FONT>;</P> <P><FONT size=+0>2) </FONT>在<FONT size=+0>vs.net </FONT>环境中,点击菜单:文件<FONT size=+0>-></FONT>新建<FONT size=+0>-></FONT>项目;</P> <P><FONT size=+0>3) </FONT>在新建项目对话框中,在左侧项目类型面板中选择<FONT size=+0> Visual Basic </FONT>项目;</P> <P><FONT size=+0>4) </FONT>在右侧的模板面板中选择类库;</P> <P><FONT size=+0>5) </FONT>命名项目为<FONT size=+0>VBNetCmds</FONT>,并且选择项目存储的路径;</P> <P><FONT size=+0>6) </FONT>点击确定,这样就新建了一个项目。<FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0></FONT></FONT></FONT></FONT></FONT></FONT></P> <P><STRONG>2.2 引用ESRI 对象库</STRONG></P> <P>在正常使用<FONT size=+0>ESRI</FONT>提供的<FONT size=+0>dotnet</FONT>对象库之前,你必须将必须的<FONT size=+0>ESRI</FONT>对象库引用到当前项目中。<FONT size=+0>ESRI</FONT>对象库在安装<FONT size=+0>Devkit </FONT>开发包时被安装,默认的安装路径为:<FONT size=+0>ArcGIS</FONT>安装根目录<FONT size=+0>\DotNet </FONT>。</P> <P><FONT size=+0>1) </FONT>点击项目菜单,然后点击添加引用子菜单,添加引用对话框打开后,选择<FONT size=+0>.net </FONT>标签,依次选择<FONT size=+0>ESRI.ArcGIS.Geometry</FONT>,<FONT size=+0>ESRI.ArcGIS.SystemUI</FONT>,<FONT size=+0>ESRI.ArcGIS.Framework</FONT>,<FONT size=+0>ESRI.ArcGIS.Carto</FONT>四个<FONT size=+0>ESRI</FONT>对象库,在本项目中还会用到其它几个对象库,如<FONT size=+0>System.Drawing</FONT>等,这时可以同时选择。</P> <P><FONT size=+0>2) </FONT>点击确定,关闭添加引用对话框,同时完成必需引用的添加。</P> <P>说明:</P> <P><FONT size=+0>ESRI.ArcGIS.Geometry </FONT>引用是因为在后面的代码中会使用到<FONT size=+0> Iextent </FONT>,<FONT size=+0>Ipoint </FONT>等接口;</P> <P><FONT size=+0>ESRI.ArcGIS.SystemUI </FONT>引用是因为要用来<FONT size=+0>Icommand </FONT>等接口;</P> <P><FONT size=+0>ESRI.ArcGIS.Carto</FONT></P> <P><FONT size=+0>ESRI.ArcGIS.Framework</FONT></P><FONT size=+0><FONT size=+0> <H2><FONT size=+0>2.3</FONT> 创建一个放大命令</H2> <P>可以使用<FONT size=+0>Com</FONT>类向导向项目中添加一个新类。</P> <P><FONT size=+0>1) </FONT>在解决方案资源管理器中,右击项目,点击添加,然后选择添加新项;</P> <P><FONT size=+0>2) </FONT>在添加新项对话框中,在右侧面板选择<FONT size=+0>Com</FONT>类,在对话框底部的名称文本框中输入此<FONT size=+0>Com</FONT>类的名称,本例中为<FONT size=+0>NetZoomIn.Vb</FONT>。</P> <P><FONT size=+0>3) </FONT>在解决方案资源管理器中,右键点击已存在的类(<FONT size=+0>Class1.VB</FONT>),然后点击删除,将项目创建时自动创建的类删除。</P> <H2><FONT size=+0>2.4</FONT> 添加<FONT size=+0> Imports </FONT>部份:</H2> <P>添加<FONT size=+0>Imports </FONT>表达式,可以简化代码的编写,使代码具有更好的可读性。</P> <P><FONT size=+0>1) </FONT>在解决方案资源管理器中,双击<FONT size=+0>NETZoomIn.VB</FONT>,打开它的代码编辑窗口。</P> <P><FONT size=+0>2) </FONT>在代码窗口的顶部,类声明的起始部份添加如下的代码;</P></FONT> <H5><FONT color=#cc0000>Imports ESRI.ArcGIS.SystemUI '定义Icommand、ITool等接口<BR>Imports ESRI.ArcGIS.ArcMapUI '定义ImxApplication、IDataWindow等接口<BR>Imports ESRI.ArcGIS.Geometry '定义IGeometry、IPoint等接口<BR>Imports ESRI.ArcGIS.Framework '定义IcommandBar、IDocument、IdockbleWindow等接口<BR>Imports ESRI.ArcGIS.Carto '定义IFeatureLayer、ICADLayer 等接口<BR>Imports System.Drawing '命令使用的图标位图IBitmap接口等<BR>Imports System.Runtime.InteropServices '</FONT></H5> <H4>2.5 实现 Icommand 接口:</H4><FONT size=+0> <P><FONT size=+0>1) </FONT>在<FONT size=+0>NetZoomIn.VB</FONT>代码窗口,可以使用如下代码声明<FONT size=+0>NetZoomIn</FONT>类实现<FONT size=+0>Icommand</FONT>接口:</P> <P><FONT size=+0> </FONT>Public Class NetZoomIn<BR></P><PRE><FONT color=#000066> </FONT>Implements<FONT color=#000066> ICommand<BR></FONT></PRE> <P><FONT size=+0>2) </FONT>在<FONT size=+0>NetZoomIn </FONT>类代码窗口顶部的向导栏,点击左侧的下接列表,并选中<FONT size=+0>Icommand</FONT>;</P> <P><FONT size=+0>3) </FONT>在右侧的下接列表中,选择<FONT size=+0>Icommand </FONT>接口的第一个成员<FONT size=+0> Bitmap</FONT>,<FONT size=+0>Bitmap</FONT>属性的代码框架将被添加到代码窗口中;</P> <P><FONT size=+0>4) </FONT>重复<FONT size=+0>2)-3)</FONT>步,将所有<FONT size=+0>Icommand </FONT>接口的成员代码框架添加到代码窗口中;</P> <P><FONT size=+0>5) </FONT>点击<FONT size=+0> Ctrl+Shift+S </FONT>,保存项目中所有的文件。</P></FONT> <H4>2.6 添加Icommand接口成员代码:</H4><FONT size=+0> <P>现在开始向<FONT size=+0>Icommand</FONT>接口的成员中添加代码。</P> <P><FONT size=+0>1) </FONT>向类中添加如下所示的代码段,下面的变量成员将被<FONT size=+0>Icommand</FONT>接口所使用。</P></FONT> <H5><FONT color=#cc0000> Public Class NetZoomIn<BR> Implements ICommand<BR> Private m_app As IApplication 'ArcMap应用程序接口<BR> Private m_enabled As Boolean '此命令是否有效<BR> Private m_bitmap As Bitmap '此命令显示于工具栏上的位图<BR> Private m_hBitmap As IntPtr '位图指针</FONT><BR></H5><FONT size=+0><PRE><FONT color=#000066>#</FONT>Region<FONT color=#000066> "COM GUIDs" <FONT color=#f709c7 size=5><STRONG>??这里的GUID怎么取得??</STRONG></FONT><BR></FONT></PRE><PRE>成员变量在类定义的开始部份进行声明。<BR></PRE> <P><FONT size=+0>2) </FONT>在<FONT size=+0>NetZoomIn</FONT>代码窗口,卷动并找到<FONT size=+0>OnCreate </FONT>方法,添加如下代码到该方法:</P></FONT> <H5><FONT color=#cc0000>Public Sub OnCreate(ByVal hook As Object) Implements ESRI.ArcGIS.SystemUI.ICommand.OnCreate<BR> '该类创建时实现的功能,引用ArcMap应用程序,并使用该命令处于有效状态<BR> If Not (hook Is Nothing) Then<BR> If TypeOf (hook) Is IMxApplication Then<BR> m_app = CType(hook, IApplication)<BR> m_enabled = True<BR> End If<BR> End If<BR>End Sub</FONT></H5><FONT size=+0> <P><FONT size=+0>3) </FONT>向上卷动代码窗口,找到<FONT size=+0><EM>OnClick</EM> </FONT>方法,添加如下代码以完成当前活动视图的放大动作:</P></FONT> <H5><FONT color=#cc0000>Public Sub OnClick() Implements ESRI.ArcGIS.SystemUI.ICommand.OnClick<BR> '鼠标点击该命令按钮时,实现的功能<BR> Dim mxDoc As IMxDocument = CType(m_app.Document, IMxDocument)<BR> Dim activeView As IActiveView = mxDoc.ActiveView<BR> Dim currExtent As IEnvelope = activeView.Extent<BR> currExtent.Expand(0.5D, 0.5D, True)<BR> activeView.Extent = currExtent<BR> activeView.Refresh()<BR>End Sub</FONT></H5><FONT size=+0> <P><FONT size=+0>4) </FONT>编辑代码块,以实现<FONT size=+0><EM>Category</EM> </FONT>,<FONT size=+0><EM>Caption</EM> </FONT>,<FONT size=+0><EM>Checked</EM> </FONT>,<FONT size=+0><EM>Enabled</EM> </FONT>,<FONT size=+0> <EM>Helpfile</EM> </FONT>,<FONT size=+0><EM>HelpContextID</EM> </FONT>,<FONT size=+0> <EM>Name</EM> </FONT>,<FONT size=+0> <EM>Message</EM> </FONT>,<FONT size=+0> </FONT>以及<FONT size=+0> <EM>Tooltip</EM> </FONT>等方法,实现该命令的一些返回信息。</P></FONT> <H5><FONT color=#cc0000>Public ReadOnly Property Caption() As String Implements ICommand.Caption<BR> Get<BR> Return "放大工具"<BR> End Get<BR> End Property<BR> Public ReadOnly Property Category() As String Implements ICommand.Category<BR> Get<BR> Return "NetCmds"<BR> End Get<BR> End Property<BR> Public ReadOnly Property Checked() As Boolean Implements ICommand.Checked<BR> Get<BR> Return False<BR> End Get<BR> End Property<BR> Public ReadOnly Property Enabled() As Boolean Implements ICommand.Enabled<BR> Get<BR> Return m_enabled<BR> End Get<BR> End Property<BR> Public ReadOnly Property HelpContextID() As Integer Implements ICommand.HelpContextID<BR> Get<BR> Return 0<BR> End Get<BR> End Property<BR> Public ReadOnly Property HelpFile() As String Implements ICommand.HelpFile<BR> Get<BR> End Get<BR> End Property<BR> Public ReadOnly Property Message() As String Implements ICommand.Message<BR> Get<BR> Return "当前视图放大一倍显示."<BR> End Get<BR> End Property<BR> Public ReadOnly Property Name() As String Implements ICommand.Name<BR> Get<BR> Return "NetCmds_放大工具"<BR> End Get<BR> End Property<BR> Public ReadOnly Property Tooltip() As String Implements ICommand.Tooltip<BR> Get<BR> Return "放大一倍"<BR> End Get<BR>End Property</FONT></H5> <H4>2.7 完成工具的图标部份(Icommand::Bitmap)</H4><FONT size=+0> <P>现在需要添加一个已存在的位置文件到当前项目中,做为本命令按扭显示的图标,这里要添加对<FONT size=+0> System.Drawing </FONT>库的引用。</P> <P><FONT size=+0>1) </FONT>在解决方案资源管理器窗口,右击<FONT size=+0>VBNetCmds</FONT>项目,然后点击添加,并选择添加现有项;(<FONT size=+0>[</FONT>图七<FONT size=+0>]</FONT>)</P> <P><FONT size=+0>2) </FONT>在添加现有项对话框中,在文件类型部份的下接列表中选择图像文件,并定位到要添加的位置文件(本例中为<FONT size=+0>ZoomIn.BMP</FONT>),点击打开按钮,将该位图添加到项目中。(<FONT size=+0>[</FONT>图八<FONT size=+0>]</FONT>)</P> <P><FONT size=+0>3) </FONT>在解决方案资源管理器窗口中,选择刚刚添加的<FONT size=+0>ZoomIn.BMP</FONT>项目,在下面的属性窗口中的生成操作条目的下接列表中选择嵌入的资源选项。<FONT size=+0> </FONT>(<FONT size=+0>[</FONT>图九<FONT size=+0>]</FONT>)</P> <P><FONT size=+0>4) </FONT>返回到该命令的代码窗口,添加如下的代码到类构结构中:</P></FONT> <H5><FONT color=#cc3300>Public Sub New()<BR> MyBase.New()<BR> Dim res() As String = GetType(NetZoomIn).Assembly.GetManifestResourceNames()<BR> If (res.GetLength(0) > 0) Then<BR> m_bitmap = New _ Bitmap(GetType(NetZoomIn).Assembly.GetManifestResourceStream(res(0)))<BR> If Not (m_bitmap Is Nothing) Then<BR> m_bitmap.MakeTransparent(m_bitmap.GetPixel(1, 1))<BR> m_hBitmap = m_bitmap.GetHbitmap()<BR> End If<BR> End If<BR>End Sub</FONT><BR>注意:GetHbitmap 方法不受控的 Windows GDI 位图对象,这个对象必须使用特定的方法进行删除,因为 .net 垃圾收集器不能清除不受控的资源。可以在如下的两个步骤5) 及 6) 中完成删除操作。 </H5><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0> <P><FONT size=+0>5) </FONT>向上卷动代码窗口,在类声明内部添加如下代码:</P></FONT></FONT></FONT></FONT> <H5><FONT color=#cc3300>Public Class NetZoomIn<BR> Implements ICommand<BR> _<BR> Private Shared Function DeleteObject(ByVal hObject As IntPtr) As Boolean<BR>End Function</FONT><BR></H5><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0> <P><FONT size=+0>DllImport </FONT>表达式部份提供了对<FONT size=+0>GDI32.DLL </FONT>库中的<FONT size=+0> DeleteObject </FONT>函数的访问声明。</P> <P><FONT size=+0>6) </FONT>向下卷动代码窗口,在类结构的底部添加如下代码:</P></FONT></FONT></FONT></FONT> <H5><FONT color=#cc3300>Protected Overrides Sub Finalize()<BR> If (m_hBitmap.ToInt32() <> 0) Then<BR> DeleteObject(m_hBitmap)<BR> End If<BR>End Sub</FONT><BR><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0>以上这段代码在垃圾收集器需要消毁<FONT size=+0>NetZoomIn </FONT>类实例时被调用,<FONT size=+0> </FONT>它重载了<FONT size=+0> System.Object. Finalize </FONT>方法。 <P><FONT size=+0>7) </FONT>最后添加如下代码到<FONT size=+0>Icommand::Bitmap</FONT>方法中,并返回<FONT size=+0>Bitmap</FONT>名柄。</P></FONT></FONT></FONT></FONT></H5> <P><FONT size=+0>7) </FONT>最后添加如下代码到<FONT size=+0>Icommand::Bitmap</FONT>方法中,并返回<FONT size=+0>Bitmap</FONT>名柄。</P> <H5><FONT color=#cc0000>Public ReadOnly Property Bitmap() As Integer Implements ICommand.Bitmap<BR> Get<BR> Return m_hBitmap.ToInt32()<BR> End Get<BR>End Property</FONT></H5> <H4>2.8 声明你的类为Com</H4><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0> <P><FONT size=+0>ArcGIS</FONT>要求你的命令类为<FONT size=+0>COM</FONT>类,因此你创建的类必须声明为<FONT size=+0>COM</FONT>,可以为它创建一个可调用的<FONT size=+0>Com</FONT>封装。</P> <P>如果你在项目开始时,使用<FONT size=+0>COM</FONT>类向导来创建你的类,那么<FONT size=+0>VB.NET</FONT>将会自动的做这些事情,而不用你在后期手动添加。</P> <P><FONT size=+0></P></FONT></FONT></FONT></FONT> <H4>2.9 添加Com分类 注册函数</H4><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0> <P>这个工作可以借助<FONT size=+0>Addins For .net </FONT>工具来完成,也可以手工方式添加代码。本示例实现的为<FONT size=+0>IMxCommands </FONT>小类的注册<FONT size=+0> </FONT>,<FONT size=+0>IMxCommands </FONT>的注册表标识<FONT size=+0>GUID</FONT>值为:<FONT size=+0>{B56A7C42-83D4-11D2-A2E9-080009B6F22B} </FONT>。</P> <P><STRONG>手工方式添加:<BR></STRONG></P> <P>将如下所示代码添加到代码窗口类声明顶部,<FONT size=+0>Com Guids Region </FONT>底部:</P></FONT></FONT></FONT></FONT></FONT> <H5><FONT color=#cc0000>#Region "Component Category Registration"<BR> _<BR> Public Shared Sub RegisterFunction(ByVal sKey As String)<BR> Dim fullKey As String = sKey.Remove(0, 18) ; "\Implemented Categories"<BR> Dim regKey As Microsoft.Win32.RegistryKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(fullKey, True)<BR> If Not (regKey Is Nothing) Then<BR> regKey.CreateSubKey("{B56A7C42-83D4-11D2-A2E9-080009B6F22B}")<BR> End If<BR> End Sub<BR> _<BR> Public Shared Sub UnregisterFunction(ByVal sKey As String)<BR> Dim fullKey As String = sKey.Remove(0, 18) ; "\Implemented Categories"<BR> Dim regKey As Microsoft.Win32.RegistryKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(fullKey, True)<BR> If Not (regKey Is Nothing) Then<BR> regKey.DeleteSubKey("{B56A7C42-83D4-11D2-A2E9-080009B6F22B}")<BR> End If<BR> End Sub<BR>#End Region<BR></FONT>通过Devkit Addin for .net 工具自动生成:<BR></H5><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0> <P>在<FONT size=+0>VS.NET IDE </FONT>环境中,在主菜单中选择<FONT size=+0> </FONT>工具<FONT size=+0>-> ESRI ComponentCategoryRegistar </FONT>,打开<FONT size=+0> Component Category Registering </FONT>对话框,在下面的列表中选择<FONT size=+0> MxCommands </FONT>,使其前面的复选框处于选中状态,然后点击<FONT size=+0>OK</FONT>按钮,如下代码会自动添加到代码窗口中:</P> <P align=center> </P><FONT size=+0><FONT size=+0> <P align=center><FONT size=+0></P></FONT></FONT></FONT></FONT></FONT></FONT></FONT> <H5><FONT color=#cc0000>#Region "Component Category Registration"<BR> _<BR> Public Shared Sub Reg(ByVal regKey As String)<BR> MxCommands.Register(regKey)<BR> End Sub<BR> _<BR> Public Shared Sub Unreg(ByVal regKey As String)<BR> MxCommands.Unregister(regKey)<BR> End Sub<BR>#End Region</FONT><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0> <P>这段代码与上面手工添加的代码功能是一样的。但使用这个<FONT size=+0>Addin </FONT>工具在工程的<FONT size=+0>BIN</FONT>目录中会生成两个批处理文件:<FONT size=+0>Reg.Bat </FONT>及<FONT size=+0> UnReg.Bat </FONT>,用于手工注册或手工取消注册生成的<FONT size=+0>DLL </FONT>文件。</P> <P><FONT size=+0>Reg.Bat </FONT>文件内容为:</P> <P><FONT size=+0>regasm VBNetCmds.dll</FONT></P> <P>请将内容改为:</P> <P><FONT size=+0>regasm VBNetCmds.dll /tlb: VBNetCmds.tlb /codebase</FONT></P> <P><FONT size=+0>Unreg.Bat</FONT>文件内容为:</P> <P><FONT size=+0>regasm VBNetCmds.dll /u</FONT></P> <P><FONT size=+0>regasm </FONT>为<FONT size=+0>.net framework </FONT>提供的<FONT size=+0>.net com </FONT>组件注册工具,位于</P> <P><FONT size=+0>SYSTEMROOT:\WINDOWS\Microsoft.NET\Framework\v1.1.4322 </FONT>目录中。请在<FONT size=+0>Path </FONT>路径设置中加入该路径。 <FONT color=#e61ae6 size=6>??这个路径要怎么添加??</FONT></P></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></H5> <H4>2.10编译项目:</H4><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0> <P>在进行项目编译之前,使用<FONT size=+0>Ctrl+Shift+S </FONT>保存项目文件所做的修改,然后在<FONT size=+0>VS.NET IDE </FONT>环境中,运行<FONT size=+0> Ctrl+Shift+B </FONT>快捷键编译项目,或通过<FONT size=+0> </FONT>菜单项<FONT size=+0> </FONT>生成<FONT size=+0> -> </FONT>生成解决方案来完成。</P> <P>如果编译成功,在结果窗口会显示以下类似信息:</P> <P>否则,如果编译不通过,代码中有拼写错误或其它错误时,将会显示类似如下的信息:</P> <P>双击出错项目描述部份,将直接来到错误出处,改正所有错误,直到出现生成成功为止。</P></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT> <H4>2.11在ArcMap环境中使用</H4><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0><FONT size=+0> <P><FONT size=+0>1) </FONT>打开<FONT size=+0>ArcMap</FONT>,点击菜单<FONT size=+0> Tools->Customize...</FONT>,打开自定义对话框:</P> <P><FONT size=+0>2) </FONT>在打开的<FONT size=+0>Customize </FONT>对话框中,点击<FONT size=+0>Commands </FONT>标签,在左侧的<FONT size=+0>Categories </FONT>列表中找到<FONT size=+0>NetCmds </FONT>分类,这时,我们刚刚做好的工具放大工具将会显示在右侧的<FONT size=+0>Commands </FONT>列表中。</P> <P><FONT size=+0>3) </FONT>拖动放大工具到指定的工具栏上,点击<FONT size=+0>Close </FONT>按钮,关闭<FONT size=+0>Customize </FONT>对话框。现在可以使用我们刚做的放大工具了。</P></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT> |
|