Autodesk官方.NET教程VB
第1章Hello World:工程的创建
在这一章中我们将不使用Obj ectARX向导来创建一个新的工程。我们将使用VisualStudio.NET来创建一个新的类库工程。通过这个工程你可以创建一个能被AutoCAD装载的.NET dll文件。这个dll文件会向AutoCAD加入一个名为―HelloWorld‖的新命令。当用户运行这个命令后在AutoCAD命令行上将显示―Hello World‖文本。
1)启动Visual Studio.NET选择‖文件>新建>工程‖(File>New>Proj ect)。在新建工程对话框中选择工程类型为‖Visual Basic工程‖然后选择‖类库‖模板在工程名字框中输入‖Lab 1‖然后选择工程存放的位置。点击确定按钮来创建工程。
2)在工程的Class1.vb文件中一个公有类―Class1‖已经被系统自动创建了。接下来向这个类加入命令。要加入命令你必须使用AutoCAD.NET托管封装类。这些托管封装类包含在两个托管模块中。要加入对这两个托管模块的引用请用鼠标右键单击‖引用‖然后选择‖添加引用‖。在弹出的‖添加引用‖对话框中选择‖浏览‖。在‖选择组件‖对话框中选择AutoCAD 2006的安装目录这里假定为C:\Program Files\AutoCAD 2006\在这个目录下找到―acdbmgd.dll‖然后选择并打开它。再一次选择‖浏览‖在AutoCAD 2006的安装目录下找到―a c mg d.dl l‖并打开它。当这两个组件被加入后请单击‖添加引用‖对话框中的‖确定‖按钮。正如它们的名字所表示的 acdbmgd.dll包含Obj ectDBX托管类而acmgd.dll包含Auto CAD托管类。
3)使用对象浏览器Visual Studio.NET的‖查看>其它窗口>对象浏览器‖菜单项来浏览加入的两个托管模块所提供的类。请展开―AutoCAD.NET Managed Wrapper‖对象在对象浏览器中显示为acmgd在整个教程中我们将使用这个对象中的类。在本章中我们将使用―Auto de s k.AutoCAD.E ditorInput.E ditor‖类的一个实例来在AutoCAD命令行中显示文本。请再展开―ObjectDBX.NET Managed Wrapper‖对象在对象浏览器中显示为acdbmgd这个对象中的类将被用来访问和编辑AutoCAD图形中的实体这部分内容将在以后的章节中介绍。
4)引用了ObjectARX.NET封装类后我们就可以导入它们。在Class 1类的声明语句位于Class 1.vb文件的顶部的之前导入ApplicationS ervices,EditorInput和Runtime命名空间。 Imports Autodesk.AutoCAD.ApplicationS ervices
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.Runtime
5)接下来在类Class1 中加入命令。要加入能在AutoCAD中调用的命令你必须使用―CommandMethod‖属性。这个属性由Runtime命名空间提供。在类Class 1中加入下列属性和子程序。注意续行符‖_‖的使用。
Public Class Class1
<C ommandMethod("HelloWorl d")>_
Public Sub HelloWorld()
End Sub
End Class
6)当―HelloWorld‖命令在AutoCAD中运行的时候上面定义的HelloWorld子程序就会被调用。在这个子程序中一个Editor类的实例将被创建。 Editor类拥有访问AutoCAD命令行的相关方法它还包括选择对象和其它一些重要的功能。AutoCAD当前活动文档的Editor对象可以使用Application类来访问。当Editor对象被创建后你可以使用它的WriteMessage方法在命令行中显示―Hello World‖文本。在HelloWorld子程序中加入以下代码
Dim ed As Editor=Application.DocumentManager.MdiActiveDocument.Editored.WriteMessage("Hello World")
7)要在AutoCAD中调试这个程序你可以让Visual Studio.NET启动一个AutoCAD进程。在解决方案管理器中右键单击―Lab 1‖然后选择‖属性‖。在Lab 1的属性页对话框中选择‖配置属性>调试‖。在‖启动‖项中选择‖启动一个外部程序‖接下来单击省略号按钮然后选择AutoCAD 2006安装目录下的acad.exe。设置好以后按F5来启动一个AutoCAD进程。这样就会编译你的程序然后自动启动AutoCAD而当编译后有错误的时候就会停止。请修正你可能碰到的任何错误。
8) ―NETLOAD‖命令被用来装载你刚才编译的托管程序。在AutoCAD命令行中输入NETLOAD会出现‖选择.NET组件‖的对话框。选择上面生成的―lab 1.dll‖然后打开它。
9)在命令行中输入―HellowWorld‖。如果一切顺利的话命令行中将显示―Hello World‖文本。切换到Visual Studio.NET在ed.WriteMessage(―Hello World‖);语句处加入一个断点。在AutoCAD中再次运行HelloWorld命令你会注意到你可以跟踪代码的运行。Visul Studio.NET的‖调试‖菜单有好几项可以用来跟踪程序的运行。
如果有时间的话请浏览一下CommandMethod属性。你会发现它有七种不同的形式。在上面的例子中我们使用了最简单的形式它只有一个输入参数命令的名字。你可以使用其它的形式来控制命令的工作方式例如你可以确定命令组的名字、全局和局部名字、命令标识命令如何来运行等。
第2章 .NET AutoCAD向导及简单用户输入
在第一章中我们使用的是类库模板这样就不得不手工加入acdb mdg. dll和acmgd.dll这两个引用。在这一章中我们将使用AutoCAD托管C#应用程序向导来创建.NET工程它会自动加入以上两个引用。在开始本章之前 你首先得安装Obj ectARX 向导(Obj ectARX2006开发包的\util s\Obj ARXWiz\ArxWizards.ms i)。
1)启动Visual Studio.NET选择‖文件>新建>工程‖(File>New>Proj ect)。在新建工程对话框中选择工程类型为‖Visual Basic工程‖然后选择―AutoCAD Managed VBProject Application‖模板。在工程名字框中输入‖Lab2‖然后选择工程存放的位置。点击确定按钮 ―AutoCAD Managed VB Application Wizard‖对话框将会出现。因为我们不需要使用非托管代码所以不要选择―Enable Unmanaged Debugging‖项。―Registered Developer Symbol‖将会使用你在安装Obj ectARX向导时输入的值。单击‖finish‖按钮来创建工程。
2)下面来看一下向导生成的工程。在解决方案浏览器中你会看到a c db mg d和a c mg d已
经被引用了。在Class.vb文件中 ―Autodesk.AutoCAD.Runtime‖命名空间已被导入工程使用
―Registered Developer Symbol‖的名字来命名缺省的公有类。 向导还为类加入了一个CommandMethod属性和一个函数它们用于AutoCAD命令。
3)在前一章中我们使用一个―Autodesk.AutoCAD.EditorInput.E ditor‖类的实例对象在Auto CAD命令行上输出文本。在这一章中我们将使用这个类来提示用户在AutoC AD图形中选择一个点然后将用户选择的点的x,y,z值显示出来。和前一章一样请导入Autodesk.AutoCAD.Applicati onS ervi ces 和 Autodesk.Auto CAD.EditorInput命名空间。Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.EditorInput
4)把向导生成的CommandMethod属性的值改为有意义一些的名字如―selectPoint‖ 函数的名字可以不用修改。PromptPointOptions类用来设置提示字符串和其它的一些控制提示的选项。这个类的一个实例作为参数被传入到Editor.GetP oint方法。在函数的开始实例化这个类 设置字符串参数为―Select a point‖ 。 因为 Editor.GetPoint方法会返回一个PromptP ointResult类的实例对象所以我们也要把它实例化。
Dim prPointOptions As PromptPointOptions=
New PromptPointOptions("Select a point")
Dim prPointRes As PromptPointResult
5)接下来实例化一个Editor类的对象并使用参数为PromptP ointOptions对象的GetP oint方法。用GetPoint方法的返回值来给上面声明的PromptPointResult对象赋值。赋值好以后我们可以测试PromptPointResult对象的状态如果不是OK就返回。
Dim ed As Editor=Application.DocumentManager.MdiActiveDocument.EditorprPointRes=ed.GetPoint(prPointOptions)
If prPointRes.Status<>PromptStatus.OK Then
Return Nothing
End If
6)如果PromptPointResult对象返回了一个有效的点我们就可以使用WriteMessage方法把结果输出到命令行。 PromptPointResult.Value的To String方法使输出非常容易ed.WriteMessage("You selected point"&prPointRes.Value.ToString())
7)按F5来运行一个调试AutoCAD的进程。 注意 向导已经设置好用acad.exe来调试在Aut o C AD命令行中输入NE TLO AD选择Lab 2.dl l并打开。在命令行中输入你起的命令名字selectPoint。在选择点的提示下单击图形中的任一点。如果一切正常的话你可以在命令行中看到你所选的点的坐标值。在Class.vb文件的―Return Nothing‖行加入断点然后再次运行selectPoint命令。这一次在选择点的提示下按ESC键而不是选择一个点。
PromptP ointResult对象的状态就不是OK了所以上面代码中的if语句就会被执行 ―ReturnNothing‖语句就会被调用。
8)接下来我们将加入另外一个命令它可以获取两个点之间的距离。 向导没有添加命令的功能所以我们必须手工添加。在Class.vb文件的选择点的函数getPoint下面添加一个名为getDistance的新命令。加入命令的方法请参考上一章的内容或本章的源代码这里就不列出了。使用CommandMethod属性并使字符串参数为―getdistanc e‖或其它类似的名字。在命令的函数中使用PromptDistanceOptions代替PromptPointOptions。当然GetDistance方法的返回值是一个PromptD oubleResult类的实例对象所以请用PromptDoubleResult来代替PromptP ointResult
Dim prDistOptions As PromptDistanceOptions =New PromptDistanceOptions("Finddistance, select first point:")
Dim prDistRes As PromptDoubleResultprD istRes=ed.GetDistance(prDistOpti ons)
9)和前面的命令一样也可以测试PromptD oubleResult的状态然后用WriteMessage方法在命令行中显示值。
If prDistRes.Status<>PromptStatus.OK Then
Return Nothing
End Ifed.WriteMessage("The distance is:"&prDistRes.Value.ToString)
第3章数据库基础:创建我们自己的Employee对象
打开Lab 3文件夹下的Lab 3工程文件或或接着Lab2的代码。在这一章中我们将创建一个‘Employee对象’ 包括一个圆一个椭圆和一个多行文本对象这个对象属于一个自定义的EmployeeBlock’块这个块驻留在‘EmployeeLayer’层 当在模型空间插入这个块的时候 ‘EmployeeLayer’层就会拥有这个块的一个块索引。本章的每一个步骤中的代码都可以运行这样做的目的可以使你更清楚地知道每一部分代码完成的功能。第一步将简要说明一下如何在模型空间创建一个圆。
< !--[i f!vml]-->
< !--[endi f]-->
这一章的重点是在AutoCAD中访问数据库的基础。主要 创建一个名为‘CREATE’ 的命令它调用函数CreateEmployee()。这个函数用来在模型空间(MODELSPACE)的10 10
0点处创建一个半径为2.0的圆
<C ommandMetho d("CREATE")>_
Public Function CreateEmployee()
‘首先声明我们要使用的对象
Dim circle As Circle ‘这个是我们要加入到模型空间的圆
Dim btr As BlockTableRecord ‘要加入圆我们必须打开模型空间
Dim bt As BlockTable ‘要打开模型空间我们必须通过块表(BlockTable)来访问它
‘我们使用一个名为‘Transaction’ 的对象把函数中有关数据库的操作封装起来
Dim trans As Transaction
‘使用TransactionManager的StartTransaction()成员来开始事务处理trans=HostApplicationServices.WorkingD atabase().TransactionManager.StartTransaction()
‘现在创建圆……请仔细看这些参数——注意创建Point3 d对象的‘New’和Vector3d的静态成员ZAxi scircle=New Circle(New Point3d(10, 10,0),Vector3 d.ZAxis,2.0)
‘我们需要获得块表和模型空间对象
‘注意我们是用事务处理的成员 GetObject 来获取它们的 bt =trans.GetObj ect(HostApplicationServices.WorkingDatabase.BlockTableId, OpenMode.ForRead)
‘现在我们声明了一个ObjectId对象用来表示模型空间块表记录…
Dim btrId As ObjectId=bt.Item(btr.ModelSpace)
‘使用这个ObjectId对象来获取块表记录对象–注意我们是打开它用来写入btr=trans.GetObj ect(btrId,OpenMode.F orWrite)
‘现在使用btr对象来加入圆btr.AppendEntity(circle)trans.AddNewlyCreatedDBObj ect(circle,True) ’并确定事务处理知道要加入圆trans.Commit() ’一旦完成以上操作我们就提交事务处理这样以上所做的改变就被保存了……trans.Dispose() ’ …然后销毁事务处理因为我们已经完成了相关的操作事务处理不是数据库驻留对象可以销毁
End Function
请仔细阅读一下上面的代码块的结构可以通过注释来了解相关的细节。
注意要编译代码你必须导入Autodesk.AutoCAD.D atabase S ervices和
Autode s k.AutoC AD.G eometry命名空间
运行这个函数来看看它是否可行。应该会在图形中创建一个在(10,10,0)处的半径为2.0的白色的圆。
2) 我们可以减少代码的输入量 这可以通过声明一个D atab a s e变量代替HostAppli cationS ervi ces.WorkingD atab ase来实现
Dim db as Database=HostApplicationServices.WorkingDatabase()
使用这个变量来代替在代码中出现的HostApplicationS ervices.WorkingD atabase()。
3) 注意 bt.Item(btr.ModelSpace)用来获取模型空间块表记录的ObjectId。我们也可以使用BlockTable的可数化属性来做同样的事bt(btr.ModelSpace)
上面的方法使代码变得容易和精简像下面一样改变有关的代码):bt=trans.GetObj ect(db.BlockTableId,OpenMode.ForRead)btr=trans.GetObj ect(bt(btr.ModelSpace),OpenMode.ForWrite)
4) 在上面的代码中我们没有使用任何异常处理而异常处理对一个正确的.NET应用程序来说是非常重要的。我们要养成使用异常处理的好习惯所以让我们在这个函数中加入Try-Catch-Finally。
5) 为了使代码紧凑我们可以把许多变量的声明和初始化放在同一个语句中。现在你的代码看起来应该是这样的
<C ommandM etho d("CREATE")>_
Public Function CreateEmployee()
Dim db As Database=HostApplicationServices.WorkingDatabase()
Dim trans As Transaction=db.TransactionManager.StartTransaction()
Try
Dim Circle As Circle=New Circle(New Point3d(10, 10,0),Vector3d.ZAxis,2.0)
Dim bt as BlockTable=trans.GetObject(db.BlockTableId,OpenMode.ForRead)
Dim btr as BlockTableRecord=trans.GetObject(bt(btr.ModelSpace),OpenMode.ForWrite)btr.AppendEntity(circle)trans.AddNewlyCreatedDBObj ect(circle,True)trans.Commit()
Catch
MsgB ox("Error Adding Entities")
Finallytrans.Dispose()
End Try
End Function
运行你的代码来进行测试……
上面的catch块只显示一个错误信息。实际的清理工作是在finally块中进行的。这样做的理由是如果在事务处理被提交Commit()之前Dispose()被调用的话事务处理会被销毁。我们认为如果在trans.C ommit()之前出现任何错误的话你应该销毁事务处理因为C ommit将永远不会被调用。如果在Dispose()之前调用了Commit()也就是说没有任何错误发生那么事务处理将会被提交给数据库。
所以基于上面的分析 Catch块其实并不是必须的 因为它只用来通知用户程序出现了一个错误。它将在下面的代码中被去掉。
6) 现在让我们在Employee加入剩下的部分椭圆和多行文本的实例。
现在让我们在Employee加入剩下的部分椭圆和多行文本的实例。
多行文本实体
中心点应该与圆心的创建一样
建议创建一个名为‘center’而值为10,10,0的Point3 d变量来表示中心点
多行文本的内容可以是你的名字。
椭圆提示你可以先看一下Ellipse的构造函数
法向量应该沿着Z轴请查看Vector3d类型
主轴设为Vector3 d(3,0,0) 提示不要忘了用new
半径比例设为0.5
椭圆还必须闭合也就是说开始和结束点必须相同
运行你的代码来进行测试……应该可以生成一个圆、一个椭圆和一个中心点在10,10,0的多行文本。
注意和事务处理对象有关的.NET API中的Try-Catch-Finally块结构应该是异常观察者。实际上我们是在try块中实例化对象的但没有显式地销毁它们。当产生异常的时候可能会产生问题特别是当观察者注意到我们实际上用的是封装的非托管对象记住当资源不再使用的时候垃圾收集机制就会回收内存。垃圾收集机制会不时的调用封装类的Dispose()方法删除非托管对象。
这里还要注意的是Dispose()作用于封装的非托管类对象的方式取决于对象是否是数据库驻留对象。 由非数据库驻留对象调用的Dispose()会删除非托管对象而由数据库驻留对象调用的Dispose()只是关闭它们。
7)接下来让我们来创建一个新的函数 它用来新建一个颜色为黄色 名字为―EmployeeLayer‖的AutoCAD层。
这个函数应该检查是否这个层已经存在但不管这个层是否存在 函数都应该返回―EmployeeLayer‖的Obj ectId。下面是这个函数的代码
Public Function CreateLayer()As ObjectId
Dim layerId As ObjectId‗它返回函数的值
Dim db As Database=HostApplicationServices.WorkingDatabase
Dim trans As Transaction=db.TransactionManager.StartTransaction()
‗首先取得层表……
Dim lt As LayerTable=trans.GetObj ect(db.LayerTableId,OpenMode.ForWrite)
‗检查EmployeeLayer层是否存在……
If lt.Has("EmployeeLayer")ThenlayerId=lt.Item("EmployeeLayer")
Else
‗如果EmployeeLayer层不存在就创建它
Dim ltr As LayerTableRecord=New LayerTableRecord()ltr.Name="Empl oye eLayer"//设置层的名字layerId=lt.Add(ltr)trans.AddNewlyCreatedDBObj ect(ltr,True)
End If
trans.Commit()trans.Dispose()
Return layerId
End Function
是不是觉得这个函数的基本结构与在模型空间加入实体的代码比较类似访问数据库的方法都是这样的使用事务处理来获取数据库对象在符号表模型空间所在的块表也是符号表之一中加入实体然后让事务处理知道。
8)在这个函数中加入异常处理就像在CreateEmployee函数中的一样。
9)接下来改变新建层的颜色。下面是实现的代码片断请把它加入到你的代码中ltr.Color=C olor.FromC olorIndex(ColorMethod.ByAci,2)
注意 ColorMethod.ByAci可以让我们使用AutoCAD ACI颜色索引……这里为2 表示黄色。
10)回到CreateEmployee()加入把上面创建的几个实体设置到EmployeeLayer层的代码。声明一个类型为Obj ectId的变量用CreateLayer函数的返回值给它赋值。使用每个实体文本、圆和椭圆的LayerId属性设置它们所在的层。
例如 text.LayerId=empId
运行代码来查看―EmployeeLayer‖层是否已被创建所有已创建的实体是否都在这一层上
应该显示为黄色
11)现在为各个实体设置不同的颜色可以使用ColorIndex属性ColorIndex属性表示Auto CAD的颜色
圆为红色1
椭圆为绿色3
文本为黄色2
运行代码看看实体的颜色是否为设置的值 即使这些实体是在―EmployeeLayer‖层上。
12)接下来我们要在AutoCAD数据库中创建一个独立的块然后把它插入到块表而不是模
型空间中。
首先把CreateEmployee函数的名字改为CreateEmployeeDefinition()。
加入以下代码来创建一个独立的块
Dim myBtr As BlockTableRecord=New BlockTableRecord()myBtr.Name="EmployeeBlock"
Dim myBtrId As ObjectId=bt.Add(myBtr)trans.AddNewlyCreatedDBObj ect(myBtr,True)
13)现在请稍微改动一下加入实体到模型空间的代码改为加入块到块表中记得加入前要打开块表。
现在运行代码然后使用INSERT命令来检查是否可以正确插入这个块。
14)最后我们要创建一个位于模型空间的块索引它表示上面创建的块的一个实例。这一步留给大家练习。
下面是你要遵循的最基本的步骤
< !--[if !supportLists]-->A) < !--[endi f]-->创建一个名为CreateEmployee新的函数
< !--[if !supp ortLi sts]-->B) < !--[endi f]-->把命令属性―CREATE‖移动到CreateEmployee()
< !--[i f !s upp ortLi sts]-->C) < !--[endi f]-->修改CreateEmployeeDefintion()来返回新创建的块―EmployeeBlock‖的ObjectId操作的步骤请参考CreateLayer()的作法。
< !--[if !supportLists]-->D) < !--[endif]-->你需要修改CreateEmployeeDefintion()来查看块表中是否已包含―EmployeeBlock‖块如果包含这个块则返回它的Obj ectId 做法与CreateLayer()一样。
提示把‘bt’ 的声明语句移动到try块的顶部使用BlockTable.Has()方法把其它的代码移动到else语句
Try
‗获取BlockTable对象
Dim bt As BlockTable = trans.GetObject(db.BlockTableId, OpenMode.ForWrite)If(bt.Has("EmployeeBlock"))ThennewBtrId=bt("EmployeeBlock") ‗已经存在……没必要创建它
Else
…
< !--[if !supportLists]-->E) < !--[endif]-->在新创建的CreateEmployee()函数中创建一个新的BlockReference对象并把它加入到模型空间。提
示我们可以使用CreateEmployeeDefinition()中引用模型空间的代码这些代码在这里不需要了
< !--[if!supportLists]-->F) < !--[endif]-->在CreateEmployee中调用 CreateEmployeeDefinition()函数 使上面生成的 BlockReference 对象的BlockTableRecord()指向CreateEmployeeDefinition()函数。提示请参考BlockReference的构造函数。
附加的问题
让我们来看一下代码的运行情况执行命令会生成一个EmployeeBlock的块索引你会看
水墨云怎么样?本站黑名单idc,有被删除账号风险,建议转出及数据备份!水墨云ink cloud Service是成立于2017年的商家,自2020起开始从事香港、日本、韩国、美国等地区CN2 GIA线路的虚拟服务器租赁,同时还有台湾、国内nat vps相关业务,也有iplc专线产品,相对来说主打的是大带宽服务器产品。注意:本站黑名单IDC,有被删除账号风险,请尽量避免,如果已经购买建议转出及数据备...
justhost怎么样?justhost是一家俄罗斯主机商,2006年成立,提供各种主机服务,vps基于kvm,有HDD和SSD硬盘两种,特色是200Mbps不限流量(之前是100Mbps,现在升级为200Mbps)。下面是HDD硬盘的KVM VPS,性价比最高,此外还有SSD硬盘的KVM VPS,价格略高。支持Paypal付款。国内建议选择新西伯利亚或者莫斯科DataLine。支持Paypal付...
licloud官方消息:当前对香港机房的接近100台物理机(香港服务器)进行打折处理,30Mbps带宽,低至不到40美元/月,速度快,性价比高,跑绝大多数项目都是绰绰有余了。该款香港服务器自带启动、关闭、一键重装功能,正常工作日内30~60分钟交货(不包括非工作日)。 官方网站:https://licloud.io 特价香港物理服务器 CPU:e3-1230v2(4核心、8线程、3.3GH...