英语原 X
查看原始 X

第五课:挑剔

beplay官网客服电话涉及的产品和版本
AutoCAD

我的第一个AutoCAD插件概述>>第一课>>教训2>>第三课>>4课>>5课>>第六课>>第七课>>8课

在接下来的几节课中,您将修改在第1课中编写的代码,为插件添加一些额外的功能。在本课中,您将修改您的代码,以便在您的自定义命令运行时提示用户提供一些信息。而不是否决TransformBy每个块属性的行为(AttributeReference对象),您将要求用户选择一个块插入(BlockReference),包括AttributeReferences他们想要否决,然后您将使用该用户选择对否决应用筛选器。

提供反馈:请通过电子邮件提供关于本次AutoCAD培训或本课的反馈:myfirstplugin@autodesk.com

课程下载

lesson5_AutoCAD_2023_projects(zip - 21kb)
lesson5_archive_2022_and_earlier_project_files(zip - 123kb)

用户输入

如果您在上一课之后关闭了Visual Studio社区,现在重新启动它并打开您的KeepAttributesHorizontal项目。按<Ctrl + Shift + F9>删除您在项目中设置的任何断点。

在接下来的代码片段中,我们将展示必须添加的新代码大胆的,以及必须在擦除中删除的代码。

要求用户输入需要一些以前没有使用过的类,这些类包含在AutoCAD API中的两个新名称空间中。添加进口在MyCommand.vb顶部的三个Imports指令下面的两个新命名空间的指令:

进口Autodesk.AutoCAD.Runtime
进口Autodesk.AutoCAD.DatabaseServices
进口Autodesk.AutoCAD.Geometry
进口Autodesk.AutoCAD.ApplicationServices
进口Autodesk.AutoCAD.EditorInput

现在添加以下代码ImplementOverrule ()方法。像以前一样,我们建议你输入这段代码(而不是复制和粘贴),这样你就可以体验Visual Studio智能感知的运行:

< CommandMethod (KeepStraight) >
公共共享子实现verrule()

             
Dim doc As文档=
Application.DocumentManager.MdiActiveDocument
暗淡的As编辑=文件。编辑器

             
选择一个块引用

             
选择“Dim As New”PromptEntityOptions (
vbLf & "选择一个块引用:")
选择。SetRejectMessage(vbLf & "必须是块引用…")
opts.AddAllowedClass(方法(BlockReference),真的)

             
暗淡的保留PromptEntityResult = ed.GetEntity(opts)

             
如果res.Status <> PromptStatus. sh那好吧
退出子
如果

这段代码将提示用户输入一些信息,但您还没有对这些信息做任何操作。尽管如此,现在是测试这段代码如何使AutoCAD运行的好时机。

  • 新闻F5从调试器启动AutoCAD。
  • NETLOAD编译后的DLL并加载示例图
  • 属性的开始处设置断点ImplementOverrule ()方法,以便您可以逐级检查代码并检查PromptEntityResults的调用返回的对象GetEntity ()
  • 运行KEEPSTRAIGHT命令几次并测试以下内容:
    • 选择一个BlockReference在提示符处。
    • 画一个在运行KEEPSTRAIGHT命令,并尝试在命令期间选择它。
    • 在提示符下按
    • 在提示符下按

的返回值,并观察AutoCAD命令行的输出res.Status为每一个。

文档而且应用程序类中的类欧特克。AutoCAD应用程序Services名称空间;和编辑器PromptEntityOptions而且PromptEntityResult类来自Autodesk.AutoCAD.EditorInput名称空间。

这个新代码首先设置医生变量指向Document对象,该对象表示当前在AutoCAD中打开并激活的绘图文档(您正在编辑的文档)。全球应用程序对象使您可以访问它的DocumentManager属性,从而使您可以访问AutoCAD中打开的所有文档。的DocumentManager具有返回MdiActiveDocument.然后存储活动文档的编辑器对象(医生)在艾德变量。

在告诉AutoCAD提示用户输入之前,必须设置一些输入选项。您可以通过创建一个新的PromptEntityOptions对象,因为您将提示用户选择实体

  • 您为AutoCAD提供了在命令行上显示的提示消息- "选择一个块引用:”(vbLF常量只是在字符串的开头添加换行符——以确保提示符从新行开始)。
  • 您指定了一个消息,如果用户选择了错误的对象类型(SetRejectMessage).
  • 您告诉AutoCAD只允许用户进行选择BlockReference对象(AddAllowedClass).AutoCAD将显示您在SetRejectMessage如果用户选择了其他内容。

现在您已经设置了提示选项,您可以调用GetEntity方法,传入您的选项。此方法返回一个PromptEntityResult来告诉你BlockReference用户选择。但是,用户可能已经通过按取消了选择,或者按执行了空选择。的如果语句立即退出ImplementOverrule ()方法(退出子)如果用户没有选择aBlockReference(即状态归来者的PromptEntityResult除了好吧).

AutoCAD API提供了许多编辑器。GetXXX方法和相应的选项和结果类,允许您提示用户进行不同类型的输入:

  • GetCorner-提示输入一个点,表示矩形的角
  • GetDistance-提示线性距离
  • -提示输入(双精度)浮点数
  • GetEntity-单个实体的提示符
  • GetInteger-提示输入整数
  • GetKeyword-提示从关键字列表中输入关键字
  • GetPoint-提示一个点
  • GetSelection-提示选择集(多个实体)
  • GetString-提示输入字符串
  • GetFileNameForOpen-显示标准AutoCAD文件打开对话框
  • GetFileNameForSave-显示标准AutoCAD文件保存对话框

否决过滤器

现在您将使用用户所做的选择来筛选您的否决行为。你要告诉AutoCAD只对AttributeReferencesBlockReference用户选择,而不是其当前行为的否决每BlockReference在图中。

添加以下代码(在大胆的,记住):

如果res.Status <> PromptStatus. sh那好吧
退出子
如果

             
Dim objIds() AsObjectId
Dim db AsDatabase = doc。数据库
使用反式a事务=
db.TransactionManager.StartTransaction

             
打开BlockReference以供读取。
“我们知道它是一个BlockReference,因为我们设置了一个过滤器
'我们的PromptEntityOptions
暗淡blkRef AsBlockReference =
trans.GetObject (res。ObjectId,OpenMode。ForRead)
'记录所有AttributeReferences的ObjectIds
’附加到BlockReference。
Dim attRefColl AsAttributeCollection =
blkRef。一个ttributeCollection
ReDim objIds (attRefColl.Count)
attRefColl。CopyTo(objIds,0)
ReDim保存objIds(attRefColl.)计数- 1)
结束使用

             
'我们只想创建一次overrule实例,
’所以我们在创建它之前检查它是否已经存在
’(也就是说,这可能是我们第二次执行该命令)
如果myOverrule是Nothing那么

这:

如果

             
'指定哪些属性将被否决
myOverrule.SetIdFilter (objIds)

             
确保“否决”被打开,这样我们的“否决”才能生效
否决。否决=真

是时候再次测试代码了:

  1. 属性的开始处设置的断点ImplementOverrule ()方法,然后按F5.一旦AutoCAD加载,NETLOAD插件,并打开测试绘图。
  2. 运行KEEPSTRAIGHT命令并选择矩形块。
  3. 运行旋转命令在绘图中的每个块插入项上执行。您会注意到,当您在旋转命令时,属性会随着块一起旋转,直到您在绘图中单击以设置最终旋转为止。然后所有属性突然跳转到与WCS x轴平行。这是因为AutoCAD在对块进行跳治时复制了块及其属性。副本有一个不同的ObjectId原件,所以副本不会被否决。当你完成旋转时,这个块看起来像这样:

//www.ocatasi.com/knowledge/sites/default/files/being_selective.gif

这段新代码引入了一些新概念,所以让我们仔细研究一下。

第一行——将objIds()设置为ObjectId-是一个变量声明,就像您之前看到的一样,但这次您声明的是一个数组.数组变量存储一组相同类型的对象。如果在声明数组时知道要在数组中存储多少对象,则在括号内放入一个数字以指定数组将存储的对象数量。数组是从零开始的,所以'昏暗的objIds (9)作为ObjectId会告诉我们会有的10该数组中ObjectId类型的对象——位于数组位置0、1、2、3、4、5、6、7、8和9。

当你申报时objIds,您还不知道它需要多大,所以您没有在括号中指定大小。方法在稍后的代码中设置数组的大小ReDim关键字。

在下一行中,我们使用数据库第一次上课。Database类表示DWG文件的全部内容。每一个文档对象关联到数据库对象(医生。数据库属性)。

接下来,我们看到使用第一次声明。的使用语句定义范围事务变量反式.当代码执行通过结束使用声明中反式变量超出作用域,它持有的对象将被. net Framework释放。的使用语句是一种很好的方法,可以确保在您希望的时间对对象进行清理。如果没有它,清理不需要的对象就留给了. net Framework“垃圾回收器”,它只在系统处理器有空闲时间时运行。在AutoCAD API中有一些对象,当你不需要它们时,将它们留在那里是一个非常糟糕的主意,因为它们只在清理时释放AutoCAD资源(处理).事务对象就是其中之一。

我们将解释交易更详细地讲晚些时候.现在,您只需要知道,每当您想要查询或编辑DWG数据库中的对象时,都需要使用这样的Transaction。交易是由调用StartTransaction ()方法数据库对象(该对象将创建一个事务对象),当事务对象被处理(在结束使用声明)。

现在你已经开始了事务,使用它来检索BlockReference对象从用户选择的图形中获取。这是使用Transaction.GetObject ()方法。的PromptEntityResult返回的对象Editor.GetEntity ()有一个ObjectId财产。ObjectId是唯一标识符对于每一个DBObject在AutoCAD会话中。的GetObject ()方法告诉AutoCAD数据库返回对应于作为参数传入的ObjectId的对象。(你知道这一定是个BlockReference因为我们设置了PromptEntityOptions只允许用户选择BlockReference。的第二个参数GetObject ()讲述了数据库是否要编辑对象(OpenMode。ForWrite)或只查询其属性而不更改它们(OpenMode。ForRead).你只需要查询这个BlockReference的属性,所以你使用OpenMode。ForRead

现在你有了BlockReference对象,你要找到它AttributeReferences黑色。一个ttributeCollection属性)。的AttributeCollection属性返回ObjectIdCollection(一个集合有点像数组)。这是我们知道数组需要多大的地方。AttributeCollection有一个属性中使用的ReDim语句将数组设置为容纳所有objectidAttributeCollection

将数组设置为正确的大小后,使用AttributeReference.CopyTo ()方法复制objectid在所有的AttributeReferences集合中的数组。

我们说过数组是从零开始的。使用设置数组的大小attRefColl。数实际上创建了一个比我们需要的多一个元素的数组。我们必须这么做,因为一个怪癖AttributeCollection。CopyTo方法——它要求在要复制到的数组中至少有一个额外的元素。第二个ReDim声明- - - - - -ReDim保存objIds(attRefColl.)计数- 1)-移除该备用数组元素。的保存关键字告诉. net运行时,它必须保留已经为数组中未被删除的元素设置的值。没有保存关键字,它们都将被重置为nullobjectid

你做的最后一个改变是打电话给否决者SetIdFilter ()方法。这就是为什么你要复制objectidAttributeCollectionobjIds数组变量。SetIdFilter ()需要数组作为参数,而不是集合。通过调用SetIdFilter ()方法(myOverrule。SetIdFilter()),您正在告诉否决规则仅应用于具有ObjectId包含在传入的数组中。

overrule有五种类型的过滤器。你可以通过调用Overrule SetXXX方法来设置你想要的过滤器类型:

  • SetIdFilter-仅对传递给该函数的数组中有ObjectId的对象应用overrule
  • SetXdataFilter—仅对具有指定注册应用程序Id的Xdata的对象应用否决。
  • SetExtensionDictionaryEntryFilter—仅对扩展字典中有指定名称的条目的对象应用该否决规则。
  • SetCustomFilter您还可以重写否决规则的isapplied()方法,以应用您自己的逻辑测试来决定是否否决特定对象。如果应该应用否决,则从isapplied()返回True。
  • SetNoFilter-如果你不调用其他方法之一,这是默认的-它应用overrule到你注册过滤器的类类型的每个对象。

你在第1课中隐式地使用了SetNoFilter()(默认);你现在正在使用SetIdFilter();稍后您将使用SetXdataFilter()。Xdata是可以添加到DBObject中的数据,用于保存应用程序使用的信息。它是一种扩展实体数据(EED)..(SetXdataFilter()和SetExtensionDictionaryFilter()都使用不同类型的EED。稍后您将了解EED教训

在下一课中,您将学习如何将信息保存在DWG文件中,以便您的插件在重新打开绘图时可以读取它。

额外的话题

目标(和句柄)
能够唯一地标识存储在DWG中的每个对象是非常重要的数据库.如果没有某种唯一的标识符,那么区分一个对象和另一个对象的唯一方法就是比较它们的所有属性。例如,两条线可能有不同的起点和终点,但如果它们没有,那么你就必须考虑它们是否在不同的层上或具有不同的线类型。为每个对象分配一个唯一的标识符可以让您省去如此冗长而详细的比较。当您将一个对象添加到DWG时数据库时,它被分配两个唯一标识符—anObjectID和一个处理

objectid


一个ObjectId在AutoCAD会话中是唯一的。无论你在一次会话中打开多少幅画,你永远不会找到两个相同的物体ObjectId

对象不会随绘图一起保存。当您关闭和重新打开一个图形时,其中的对象很可能具有不同的objectid.AutoCAD使用objectid跟踪绘图中对象之间的关系。但是当AutoCAD在DWG文件中保存这些关系时,它会将它们转换为处理

AutoCAD .NET APIDBObject类——所有可以存储在DWG数据库中的对象的父类——公开了一个ObjectId属性,该属性由从它派生的所有类继承。当你使用Editor.GetEntity ()方法在本课中要求用户选择BlockReference,归来者PromptEntityResult对象包含的ObjectId属性,然后使用该属性从DWG检索该对象数据库

处理
你不会使用处理在你的。net插件中。我们在这里提到它们是因为您可能在运行LIST命令时看到过它们,或者如果您曾经接触过LISP编程。

一个处理不同于ObjectID因为它在图纸中是唯一的,但在AutoCAD会话中打开的所有图纸中不是唯一的。这意味着两个物体在两幅不同的图画中可以有相同的东西处理.(尽管将Handle与绘图路径名结合使用是唯一的。)

处理与图纸一起保存。当您保存并重新打开一个图形时,每个对象将具有相同的属性处理就像上次一样。一个物体的唯一时间处理你会改变吗插入将对象放入新的绘图-然后处理必须进行更改,以避免与正在插入的图形中的Handles发生冲突。

DBObject类公开处理财产。

下表总结了两者的异同处理而且objectid

处理

ObjectId

在DWG中独一无二

是的

是的

会话唯一

没有

是的

DWG保存

是的

没有

交易
继续我们的数据库主题,我们有一个类似的机制来修改DWG,这并不奇怪数据库至于修改关系数据库,我们使用交易

一个概念事务很简单。中所做的任何更改事务都只承诺了吗数据库事务承诺。对象中修改对象时,如果出现任何错误数据库在一个事务,然后简单地中止事务数据库返回到?之前的状态事务开始了。这如下面的简单流程图所示。

//www.ocatasi.com/knowledge/sites/default/files/transactions.gif

交易非常强大,因为它们允许您在命令被取消或出现错误时轻松地回滚命令的效果。你可能已经加了100实体对象到DWG数据库当用户决定取消命令时,在自定义命令中。因为这些都是你加的实体对象使用事务时,可以通过简单地中止事务(而不是回头一个一个地删除)。如果用户完成命令而不是取消它,则只需提交事务

清理(处置)


你通常不会打电话给Transaction.Abort ()方法,因为事务如果在未提交的情况下被处理,则自动中止。

dispose是什么意思?

.NET中需要在你使用完它们之后自行清理的对象实现了处理()方法。您或.NET框架将调用处理()方法来告诉对象执行清除操作。

. net有一个“垃圾收集”的概念。这是. net框架检查您在程序中创建的所有对象,以查看您是否仍在使用它们。它假定,如果当前作用域内的代码中没有变量引用对象,则可以销毁该对象。如果对象实现了处理()方法,垃圾回收器将在销毁对象并释放它所占用的内存之前调用它。垃圾回收器在有空闲处理器时间(空闲时间)时清理对象,因此垃圾回收对象可能需要一段时间(有时需要几分钟)。

事务对象实现了处理()方法。如果您在自定义命令结束并将控制权返回AutoCAD之前没有正确地处理创建的Transaction对象,那么您将开始看到一些非常奇怪的AutoCAD行为-通常以AutoCAD崩溃告终。因此,你不能把它留给垃圾回收器——你必须调用它处理()事务一旦你用完它就反对。方法的一种方法是显式调用Transaction.Dispose ()方法。但是有一个更好的办法…

使用结束……在本课中添加到代码中的语句负责调用处理()给你。的使用声明告诉。NET你想“使用”的变量:

使用反式aTransaction = db.TransactionManager.StartTransaction

在这种情况下,你正在“使用”a事务对象中存储的变量名为反式.的结束使用语句告诉.NET立即清理你正在“使用”的对象:

结束使用

清理工作的一部分就是调用trans.Dispose()。你看不见,但这就是幕后发生的事情。如果您正在使用您的事务修改DBObjects,那么您将调用Transaction.Commit ()方法,在到达End Using语句之前将对对象的更改提交到DWG中数据库.它的代码是这样的:

使用trans As Transaction = db.TransactionManager.StartTransaction
...
trans.Commit ()
结束使用

Transaction.Dispose ()方法(当结束使用是到达)检查,看看是否Transaction.Commit ()方法已被调用。如果没有,那么处理()方法自动调用Transaction.Abort ()方法。

如果你只是在查询DBObjects在一个事务而不是修改它们,那么不管你是否提交事务与否。尽管犯下了事务如果你在你的数据库中打开大量(数千)个对象,它会比中止稍微快一些事务

底线是非常简单的-记住总是使用使用结束……交易

数组和集合


一个数组存储一组相同类型的对象的变量。你在本节课中看到,当你声明数组变量时,你可以指定数组将保存的对象数量:

将myArray(9)设为整数

你可以以后再改。这段代码向数组中添加了额外的5个元素:

ReDim myArray (14)

使用序数访问数组的元素。这段代码设置了4的值th将myArray的元素转换为42。

myArray(3) = 42

数组可以是多维的。下面的代码定义了一个10 × 10的二维数组:

将myArray(9,9)设为整数

把二维数组想象成电子表格或网格,第一个序数是行号,第二个序数是列号。你的数组可以有任意数量的维度。

数组是简单、快速和高效的,但在某些方面,数组是对。net更原始的编程框架的倒退。.NET中更高级的构造是集合简单地说,可以将集合视为一个数组,在添加和删除元素时动态增长。元素添加元素Add ()方法,并使用RemoveAt ()方法。集合只是一维的。控件访问集合中的项项目()方法。

在本教程中,您将使用AttributeCollection而且ObjectIdCollection,它们是AutoCAD . net API中的预定义集合。当您开始编写更高级的代码时,您可以创建自己的集合。下面是一些代码,将三个ObjectIds添加到一个ObjectIdCollection中,访问集合中的第2项,然后删除第1项:

Dim idColl As ObjectIdCollection
idColl.Add (id1)
idColl.Add (id2)
idColl.Add (id3)
Dim objId As ObjectId = idcol . item (2)
idColl.RemoveAt (1)

在.NET框架中有几个专门的集合类型类系统。集合名称空间,包括:

字典-存储在Dictionary中的每个对象都由唯一键引用。

SortedDictionary-类似于Dictionary,但按键值排序。

列表—大小动态变化的数组。

队列-先进先出的收集

堆栈-先进后出的收集。

我的第一个AutoCAD插件概述>>第一课>>教训2>>第三课>>4课>>5课>>第六课>>第七课>>8课

网站版本:2.132.0
Baidu
map