Autodesk官方最新的.NET教程(四)(vb.net版)

** 第 ** ** 4 ** ** 章 ** ** ** ** ** ** 数据库基础 ** ** 2 ** ** : ** ** 添加自定义数据 **

在这一章中,我们将创建一个新的字典对象,它用来表示我们雇员就职的 ‘Acme 公司 ‘ (呵呵,当然是虚构的一家公司)的部门。这个“部门”字典对象将包含一个表示部门经理的记录。我们还会加入代码到雇员创建过程,这个过程会加入一个索引到雇员工作的部门。

我们要说明的是如何在 DWG 文件中创建自定义数据,包括“每个图形”的自定义数据和“每个实体”的自定义数据。“每个图形”的自定义数据是指只在整个图形中加入一次的数据,它表示对象可以引用的单一类型或特性。“每个实体”的自定义数据是指是为特定的对象或数据库中的实体加入的数据。

在下面的示例中,我们将加入“每个图形”的自定义数据到命名对象字典 ( 简称 NOD) 。 NOD 存在于每一个 DWG 文件中。“每个实体”的自定义数据加入到一个名为“扩展字典”的字典(可选)中,它表示每一个雇员。每一个由 DBObject 派生的对象都拥有存储自定义数据的扩展字典。而在我们的示例中将包含这种自定义数据如名字、薪水和部门。

因此这一章的重点是字典对象和扩展记录( XRecord ),它们是我们用来表示自定义数据的容器。

首先让我们来创建表示公司的条目。在本章的前几个步骤中,我们将创建如下所示的部门层次结构:

_ NOD _ _ -命名对象字典 _ _ _

_ _ _ _ _ ACME_DIVISION _ _ -自定义公司字典 _ _ _

_ _ _ _ _ _ _ _ _ 销售 _ _ ( _ _ Sales _ _ ) _ _ _ _ -部门字典 _ _ _

_ _ _ _ _ _ _ _ _ 部门经理-部门条目 _ _ _

请打开 Lab4 文件夹下的 Lab4 工程,或接着 Lab3 的代码。

** 1) ** 我们首先要做的是定义一个新的函数,它用来在命名对象字典 (NOD) 中创建公司字典对象。为这个函数取名为

CreateDivision(), ,并使用命令属性来定义 CREATEDIVISION 命令。

下面是这个函数的代码,它的形式非常简单,只是用来在 NOD 中创建一个 ACME_DIVISION (用来表示公司)

  1<commandmethod("createdivision")> _ 
  2
  3Public Function CreateDivision() 
  4
  5Dim db = HostApplicationServices.WorkingDatabase 
  6
  7Dim trans As Transaction = db.TransactionManager.StartTransaction() 
  8
  9Try 
 10
 11'  首先,获取  NOD  …… 
 12
 13Dim NOD As DBDictionary = trans.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForWrite, False) 
 14
 15'  定义一个公司级别的字典 
 16
 17Dim acmeDict As DBDictionary 
 18
 19Try 
 20
 21'  如果  ACME_DIVISION  不存在,则转到  catch  块,这里什么也不做 
 22
 23acmeDict = trans.GetObject(NOD.GetAt("ACME_DIVISION"), OpenMode.ForRead) 
 24
 25Catch 
 26
 27'  如果  ACME_DIVISION  不存在,则创建它并把它加入到  NOD  中…… 
 28
 29acmeDict = New DBDictionary() 
 30
 31NOD.SetAt("ACME_DIVISION", acmeDict) 
 32
 33trans.AddNewlyCreatedDBObject(acmeDict, True) 
 34
 35End Try 
 36
 37trans.Commit() 
 38
 39Finally 
 40
 41trans.Dispose() 
 42
 43End Try 
 44
 45End Function 
 46
 47请仔细阅读一下上面的代码块的结构,可以通过注释来了解相关的细节。特别要注意的是我们是如何用一个  try-catch  块来处理  ACME_DIVISION  是否存在?如果  ACME_DIVISION  字典不存在,  GetObject()  将会抛出异常,  catch  块被执行,它会创建一个新的字典。 
 48
 49运行这个函数来看它是否可行。可以使用数据库查看工具来检查字典是否已被加入(建议使用  ARX SDK  的  ArxDbg  工具)  _ _
 50
 51** 2)  ** 接下来,我们要在  ACME_DIVISION  字典中加入销售  (Sales)  条目。销售  (Sales)  条目同样也是一个字典。由于销售  (Sales)  与  ACME_DIVISION  字典的关系如同  ACME_DIVISION  字典与  NOD  ,所以代码是类似的。定义下面的代码部分在  ACME_DIVISION  字典中创建一个名为  ’Sales’  的字典。 
 52
 53代码提示: 
 54
 55Code hint: 
 56
 57Dim divDict As DBDictionary 
 58
 59Try 
 60
 61divDict = trans.GetObject(acmeDict.GetAt("Sales"), OpenMode.ForWrite) 
 62
 63Catch 
 64
 65 66
 67_ 运行函数来看  _ _ ‘Sales’  _ _ 条目是否已加入到  _ _ ACME_DIVISION  _ _ 字典。  _ _ _
 68
 69_ _
 70
 71** 3)  ** 现在我们要在这个字典中加入一个特殊的记录,它可以包含任意的自定义数据。我们要加入的数据类型为扩展记录(  XRecord  ),它可以包含任何东西,因此我们可以让它包含  ResultBuffer  类的  对象(就是有些人可能非常熟悉的  ‘resbuf’  )。  ResultBuffer  可以存储不同类型的预定义数据。扩展记录存储任意数目的  ResultBuffer  关系列表,因此可能会很大。下表是可以包含在  ResultBuffer  中一些数据类型(位于  Database  类的  DxfCode  枚举中): 
 72
 73Start 
 74
 75| 
 76
 770 
 78
 79|   
 80  
 81---|---|---  
 82  
 83Text 
 84
 85| 
 86
 871 
 88
 89|   
 90  
 91XRefPath 
 92
 93| 
 94
 951 
 96
 97|   
 98  
 99ShapeName 
100
101| 
102
1032 
104
105|   
106  
107BlockName 
108
109| 
110
1112 
112
113|   
114  
115AttributeTag 
116
117| 
118
1192 
120
121|   
122  
123SymbolTableName 
124
125| 
126
1272 
128
129|   
130  
131MstyleName 
132
133| 
134
1352 
136
137|   
138  
139SymTableRecName 
140
141| 
142
1432 
144
145|   
146  
147AttributePrompt 
148
149| 
150
1513 
152
153|   
154  
155DimStyleName 
156
157| 
158
1593 
160
161|   
162  
163LinetypeProse 
164
165| 
166
1673 
168
169|   
170  
171TextFontFile 
172
173| 
174
1753 
176
177|   
178  
179在下面的代码部分,我们将创建只包含一个  ResultBuffer  的扩展记录。这个  ResultBuffer  包含一个单一的的字符串值,它表示  ’Sales’  部门的部门经理的名字。我们使用和加入字典一样的方法加入扩展记录。唯一的区别是扩展记录与字典的不同: 
180
181mgrXRec = New Xrecord() 
182
183mgrXRec.Data = New ResultBuffer(New TypedValue(DxfCode.Text, "Randolph P. Brokwell")) 
184
185请看一下我们是怎样使用  new  来创建一个新的扩展记录。但我们也使用了  New  来创建一个  Re  sultBuffer  ,传入的参数是一个名为  ‘TypedValue’  的对象。  ‘TypedValue’  对象和  C++  中  resbuf  的成员  ‘restype’  是类似的。这个对象一般表示一个特定类型的  DXF  值,我们使用它来组装诸如扩展数据或扩展记录之类的通用数据容器。在这里,我们简单地使用  DxfCode.Text  键值和  “Randolph P. Brokwell”  数据值来定义一个  TypedValue  ,然后把它作为单一的参数传入  ResultBuffer  构造函数  (  由  new  来调用  )  中。 
186
187XRecord  的  ’Data’  属性实际上正是扩展记录链的第一个  ResultBuffer  ,我们使用它来表示扩展记录链是从什么地方开始的。 
188
189所以接下来的代码块看起来和前面两个非常相似: 
190
191Dim mgrXRec As Xrecord 
192
193Try 
194
195mgrXRec = trans.GetObject(divDict.GetAt("Department Manager"), OpenMode.ForWrite) 
196
197Catch 
198
199mgrXRec = New Xrecord() 
200
201mgrXRec.Data = New ResultBuffer(New TypedValue(DxfCode.Text, "Randolph P. Brokwell")) 
202
203divDict.SetAt("Department Manager", mgrXRec) 
204
205trans.AddNewlyCreatedDBObject(mgrXRec, True) 
206
207End Try 
208
209_ 运行函数并使用数据库查看工具来确定部门经理已被加入到  _ _ ’Sales’  _ _ 字典。  _ _ _
210
211** 4)  ** 我们已经定义了公司字典,现在我们要把每个雇员的数据加入到前一章定义的块索引中。我们要加入的数据是:名字、薪水和雇员所属的部门。要加入这些数据,我们要同前几个步骤一样使用扩展记录。因为我们要加入三个条目,所以我们要使扩展记录可以把这些数据联系在一起。  ** **
212
213一般来说,扩展记录只能存在于字典中。而我们要为每个雇员加入这些数据(就是本章开头所讲的“每个图形”的自定义数据和“每个实体”的自定义数据),那应该怎么做呢?答案就是:每一个对象或  AutoCAD  中的实体实际上都有一个名为  ’  扩展字典(  Extension Dictionary  )  ’  的可选字典。我们可以把扩展记录直接加入到这个字典中。 
214
215请回到我们在上一章创建的  CreateEmployee()  函数。这个函数是我们创建块索引的地方。 
216
217让我们像前面的步骤一样来创建一个新的扩展记录。因为我们要加入  3  个条目,因此我们既可以使用  ResultBuffer  的  Add  方法(它会在扩展记录链中加入一个链接),也可以利用  ResultBuffer  的构造函数(它的一种构造函数可以输入可变数量的参数)。 
218
219无论用哪一种方法,请在  CreateEmployee()  函数中使用  ResultBuffer  来创建一个新的  XRecord  ,  ResultBuffer  包括以下的类型和值: 
220
221Text – “Earnest Shackleton”  (  或是你选择的其它雇员的名字  ) 
222
223Real – 72000  或者更多的薪水  J 
224
225Text – “Sales”  雇员所在的部门 
226
227** 5)  ** 要把上面的扩展记录加入到块索引,我们必须把它加入到扩展字典。通常这个字典是不存在的,除非它被明确地创建,块索引就是这种情况。要给一个对象创建扩展字典,你要调用它的成员  ‘CreateExtensionDictionary()’  。这个函数不返回任何值,所以要访问它创建的扩展字典,你还得使用对象的  ‘ExtensionDictionary  ’  属性。你可以使用类似于以下的代码来创建并访问扩展字典: 
228
229br.CreateExtensionDictionary() 
230
231Dim brExtDict As DBDictionary = trans.GetObject(br.ExtensionDictionary(), OpenMode.ForWrite, False) 
232
233由于扩展字典也是字典,我们可以和第  3  步一样在扩展字典中加入扩展记录。请完成有关的代码来创建和访问块索引的扩展字典,加入你在第  4  步中创建的扩展记录,然后把扩展记录加入到事务处理。 
234
235** 6)  ** 返回到  NOD  ……因为在  NOD  中创建公司字典只需要一次(就像创建  Employee  块一样  ),因此我们应该把  CreateDivision  函数的命令属性去掉,而在  CreateEmployeeDefinition()  中调用这个函数。请自己完成这些改变。当所有这些都做完后,当  CREATE  命令第一次运行的时候,所有的函数都会被调用。 
236
237** 7)  ** 下面的步骤和上面的无关。我们将创建一个函数来遍历模型空间,以用来查找加入的  Employee  对象(这里其实是块索引)的数目。在  VB.NET  或  C#  中,我们可以把模型空间块表记录(  ModelSpace BlockTableRecord  )当作一个集合,这样就可以使用  For Each  (C#  是  foreach  )  来遍历它。请仔细研究一下下面的代码片断: 
238
239Dim id As ObjectId ‘  首先,定义一个  For  循环要使用的  ObjectId  变量。 
240
241For Each id In btr 
242
243Dim ent As Entity = trans.GetObject(id, OpenMode.ForRead, False) '  打开当前的对象  ! 
244
245一旦我们获得模型空间对象,你们就可以定义一个  ObjectId  变量,然后把它用于  For Each  循环  (C#  是  foreach  )  。 
246
247现在,我们需要使用一些方法来筛选雇员。我们知道模型空间中的对象都是实体,但不全是雇员。我们需要使用一些方法来加以区分。在这里,我们可以使用  VB.NET  的  TypeOf  关键字并用  CType  进行类型转换(  C#  是  GetType  函数和  typeof  ): 
248
249If TypeOf ent Is BlockReference Then 
250
251Dim br As BlockReference = CType(ent, BlockReference) 
252
253254
255上面讲的概念对于  AutoCAD  编程  是很重要的,因为容器对象经常包含不同类型的对象。你会在  AutoCAD  程序的开发中经常碰到这种类型转化。 
256
257请定义一个名为  EmployeeCount()  的函数,函数的结构如上所示,它用来统计模型空间中的块索引的数目。这个函数不会输出任何东西,但你可以使用逐步调试程序来查看整数变量的增加(每发现一个块索引对象)。 
258
259** 8)  ** 接下来,为了把结果输出到命令行,我们需要使用  Application.DocumentManager.MdiActiveDocument.Editor  对象的服务。要使用它,请加入下面的代码: 
260
261Imports Autodesk.AutoCAD.EditorInput 
262
263Imports Autodesk.AutoCAD.ApplicationServices 
264
265在函数的内部: 
266
267Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor 
268
269  
270最后,在循环的后面确定找到了多少个块索引: 
271
272ed.WriteMessage("Employees Found: {0}" + ControlChars.Lf, nEmployeeCount.ToString()) 
273
274** End of Lab 4:  **
275
276** 第四章结束  ** ** **
277
278** **
279
280下面的代码片断演示了怎样获取  Employee  对象的所有内容,包括  ACME_DIVISION  字典中的部门经理的名字。这部分要在后面的章节中使用,但因为它和本章有关,因此我们把它放在本章作介绍。如果有时间的话,请阅读一下其中的代码来看看它是怎么使用的。它可以被直接放到你的类中并可以运行。命令的名字是  PRINTOUTEMPLOYEE  。  ListEmployee()  &lt;span style="font-size: 10pt; f</commandmethod("createdivision")>
Published At
Categories with Web编程
Tagged with
comments powered by Disqus