第 5 章 用户互操作:提示和选择
背景
提示通常包含一个描述性信息,伴随一个停止以让用户理解所给的信息并输入数据。数据可以通过多种方式被输入,如通过命令行、对话框或AutoCAD编辑窗口。给出的提示要遵循一定的格式,格式要与一般的AutoCAD提示相一致,这一点是非常重要的。例如,关键字要用“/”号分隔并放在方括号“[]”中,缺省值要放在“<>”内。对于一个AutoCAD用户来说,坚持统一的格式将会减少信息理解错误的产生。
当用户在AutoCAD命令行中选择一个实体时,实体是使用选择机制被选择的。这种机制包括一个提示,用来让用户知道选择什么并怎样选择(如,窗口或单一实体),然后是一个停顿。
试一下诸如PINE这种命令来看一下提示的显示,PEDIT来看一下使用单一实体或多线来进行选择。
练习
Prompts:
提示:
在本章中,我们将提示输入雇员名字、职位、薪水和部门来创建一个雇员块索引对象。如果输入的部门不存在,我们将提示输入部门经理的名字来创建一个新的部门。在我们继续之前,让我们试着重用以前的代码。
为了进行选择,我们将提示用户在一个窗口中进行选择或选择一个实体,而我们只显示选择集中的雇员对象。
在前面的章节中,我们创建了一个名叫“Earnest Shackleton”的雇员,名字被存储为“EmployeeBlock”块定义(块表记录)中的MText。如果我们多次插入这个块,那么我们看到的都是同一个雇员的名字。我们怎样才能自定义这个块以使每次插入这个块的时候显示不同雇员的名字?这就要使用块属性的功能了。属性是存储在每一个块索引实例中的文本,并被作为实例的一部分来被显示。属性从存储在块表记录中的属性定义中继承相关的属性。
属性:
让我们来把MText实体类型改变为属性定义。在CreateEmployeeDefinition()函数中,把下面的代码替换
‘ 文本:
Dim text As MText = New MText()
text.Contents = "Earnest Shackleton"
text.Location = center
为
'属性定义
Dim text As AttributeDefinition = New AttributeDefinition(center, "NoName", "Name:", "Enter Name", db.Textstyle)
text.ColorIndex = 2
试着使用TEST命令来测试一下CreateEmployeeDefinition()函数:
<CommandMethod("TEST")> _
Public Function Test()
CreateEmployeeDefinition()
End Function
你现在应该可以使用INSERT命令来插入EmployeeBlock块并对每一个实例确定一个雇员名。
当你插入Employee块时,请注意一下块插入的位置。它是正好被放置在所选点还是有些偏移?试试怎样修复它。(提示:检查块定义中的圆心)
修改CreateEmployee ()以重用
1)让我们来修改CreateEmployee()函数,以让它可以接收名字、薪水、部门和职位并返回创建的雇员块索引的ObjectId。函数的形式如下(你可以改变参数顺序)
Public Function CreateEmployee(ByVal name As String, ByVal division As String, ByVal salary As Double, ByVal pos As Point3d) as ObjectId
2) 移除上面函数中的CommandMethod属性”CREATE”,这样它就不再是用来创建雇员的命令。
3) 修改函数的代码,这样就可以正确地设置块索引的名字、职位、部门和薪水和它的扩展字典。
替换
Dim br As New BlockReference(New Point3d(10, 10, 0), CreateEmployeeDefinition())
为
Dim br As New BlockReference(pos, CreateEmployeeDefinition())
替换
xRec.Data = New ResultBuffer( _
New TypedValue(DxfCode.Text, "Earnest Shackleton"), _
New TypedValue(DxfCode.Real, 72000), _
New TypedValue(DxfCode.Text, "Sales"))
为
xRec.Data = New ResultBuffer( _
New TypedValue(DxfCode.Text, name), _
New TypedValue(DxfCode.Real, salary), _
New TypedValue(DxfCode.Text, division))
4) 因为我们把雇员的名字从MText替换成块的属性定义,因此我们要创建一个相应的属性索引来显示雇员的名字。属性索引将使用属性定义的属性。
替换:
btr.AppendEntity(br) '加入索引到模型空间
trans.AddNewlyCreatedDBObject(br, True) '让事务处理知道
为
Dim attRef As AttributeReference = New AttributeReference()
'遍历雇员块来查找属性定义
Dim empBtr As BlockTableRecord = trans.GetObject(bt("EmployeeBlock"), OpenMode.ForRead)
Dim id As ObjectId
For Each id In empBtr
Dim ent As Entity = trans.GetObject(id, OpenMode.ForRead, False) '打开当前的对象!
If TypeOf ent Is AttributeDefinition Then '
'设置属性为属性索引中的属性定义
Dim attDef As AttributeDefinition = CType(ent, AttributeDefinition)
attRef.SetPropertiesFrom(attDef)
attRef.Position = New Point3d(attDef.Position.X + br.Position.X, _
attDef.Position.Y + br.Position.Y, _
attDef.Position.Z + br.Position.Z)
attRef.Height = attDef.Height
attRef.Rotation = attDef.Rotation
attRef.Tag = attDef.Tag
attRef.TextString = name
End If
Next
btr.AppendEntity(br) '把索引加入模型空间
'把属性索引加入到块索引
br.AttributeCollection.AppendAttribute(attRef)
'让事务处理知道
trans.AddNewlyCreatedDBObject(attRef, True)
trans.AddNewlyCreatedDBObject(br, True)
研究一下上面的代码,看看是怎样把属性定义中除显示用的文本字符串外的属性复制到属性索引的。属性被加入到块索引的属性集合中。这就是你怎样来为每一个实例自定义雇员名字。
5)不要忘记返回雇员块索引的ObjectId,但要在提交事务处理之后才能返回:
trans.Commit()
Return br.ObjectId
6) 测试CreateEmployee。
加入一个Test命令来测试CreateEmployee:
<CommandMethod("TEST")> _
Public Function Test()
CreateEmployee("Earnest Shackleton", "Sales", 10000, New Point3d(10, 10, 0))
End Function
修改CreateDivision()以重用:
让我们来修改CreateDivision ()函数,以让它可以接收部门名字、经理名字并返回创建的部门经理扩展记录的ObjectId。如果部门经理已经存在,则不改变经理的名字。
1) 如果你先前在CreateEmployeeDefinition()中调用了CreateDivision(),请把它注释掉,因为我们在这里不需要创建一个部门
2) 改变CreateDivision()的形式让它接收部门和经理的名字并返回一个ObjectId。
Public Function Crea