AutoCAD .NET API(.NET)的基础知识

要有效地使用AutoCAD®.NET API,您应该熟悉与要自动执行的任务相关的AutoCAD图元、对象和功能。对对象的图形和非图形特性了解得越多,就越容易通过AutoCAD .NET API对其进行操作。

本节中的主题

  • 了解AutoCAD对象层次(.NET)
  • 访问对象层次结构(.NET)
  • 集合对象(.NET)
  • 了解属性和方法(.NET)
  • 进程外与进程内(.NET)
  • 定义命令和AutoLISP函数(.NET)

了解AutoCAD对象层次(.NET)

对象是AutoCAD .NET API的主要构造块。每个暴露的对象都代表AutoCAD的一个精确部分。AutoCAD .NET API中有许多不同类型的对象。AutoCAD .NET API中表示的某些对象包括:

  • 图形对象,如直线、圆弧、文本和尺寸
  • 样式设置,如图层、线型和标注样式
  • 组织结构,如层、组和块
  • 图形显示,如视图和视口
  • 甚至绘图和AutoCAD应用程序

这些对象以分层方式进行结构化,AutoCAD应用程序对象位于根。这种层次结构通常被称为对象模型。下图显示了 Application 对象与 BlockTableRecord (如模型空间)中的图元之间的基本关系。AutoCAD .NET API中还有许多对象未在此处表示。

本节中的主题

  • 应用程序对象(.NET)
  • 文档对象(.NET)
  • 数据库对象(.NET)
  • 图形和非图形对象(.NET)
  • 集合对象(.NET)
  • 非原生图形和非图形对象(.NET)

应用程序对象(.NET)

Application 对象是AutoCAD .NET API的根对象。从Application对象中,可以访问主窗口以及任何打开的图形。一旦有了图形,就可以访问图形中的对象。

例如, Application 对象有一个返回 DocumentCollection 对象的 DocumentManager 属性。此对象提供对当前在AutoCAD中打开的图形的访问,并允许用户创建、保存和打开图形文件。Application对象的其他属性提供对应用程序特定数据(如信息中心、主窗口和状态栏)的访问。 MainWindow 属性允许访问应用程序名称、大小、位置和可见性。

虽然Application对象的大多数特性允许访问AutoCAD .NET API中的对象,但也有一些特性引用AutoCAD ActiveX® Automation中的对象。这些属性包括应用程序对象的COM版本( AcadApplication )、菜单栏( MenuBar )、加载的菜单组( MenuGroups )和首选项( Preferences )。

DocumentManager
所有文档对象的容器(每个打开的图形都有一个文档对象)。

DocumentWindowCollection
所有文档窗口对象的容器(DocumentManager中的每个文档对象都有一个文档窗口对象)。

InfoCenter InfoCenter信息
包含对信息中心工具栏的引用。

MainWindow MainWindow的
包含对AutoCAD的应用程序窗口对象的引用。

MenuBar
包含对AutoCAD中菜单栏的MenuBar COM对象的引用。

MenuGroups
包含对MenuGroups COM对象的引用,该对象包含每个加载的CUIx文件的自定义组名称。

Preferences
包含对首选项COM对象的引用,该对象允许您修改“选项”对话框中的许多设置。

Publisher
包含对用于发布图形的Publisher对象的引用。

StatusBar
包含对应用程序窗口的StatusBar对象的引用。

UserConfigurationManager
包含一个对UserconfigureationManager对象的引用,该对象允许您使用用户保存的配置文件。

文档对象(.NET)

实际上是AutoCAD图形的 Document 对象是 DocumentCollection 对象的一部分。使用 DocumentExtension 和 DocumentCollectionExtention 对象可以创建、打开和关闭图形文件。 Document 对象提供对 Database 对象的访问,该对象包含所有图形和大多数非图形AutoCAD对象。

沿着 Database 对象, Document 对象提供对状态栏、打开文档的窗口、 Editor 和 TransactionManager 对象的访问。 Editor 对象提供对用于从用户获取输入的函数的访问,输入的形式为点、输入的字符串或数值。

TransactionManager 对象用于在称为事务的单个操作下访问多个数据库对象。事务可以嵌套,当您完成事务时,您可以提交或中止所做的更改。

数据库对象(.NET)

Database 对象包含所有图形和大多数非图形AutoCAD对象。数据库中包含的一些对象是实体、符号表和命名字典。数据库中的图元表示图形中的图形对象。直线、圆、圆弧、文字、图案填充和多段线都是图元的示例。用户可以看到屏幕上的实体,并可以操纵它。

通过 Document 对象的 Database 成员属性访问当前文档的 Database 对象。

1
Application.DocumentManager.MdiActiveDocument.Database

符号表和字典

符号表和字典对象提供对非图形对象(块、图层、线型、布局等)的访问。每个图形都包含一组九个固定的符号表,而图形中的字典数量可以根据AutoCAD中使用的应用程序的功能和类型而有所不同。无法将新符号表添加到数据库中。

符号表的示例包括图层表(LayerTable)和块表(BlockTable),前者包含图层表记录,后者包含块表记录。所有图形实体(线、圆、弧等)都属于块表记录。默认情况下,每个图形都包含模型空间和图纸空间的预定义块表记录。每个图纸空间布局都有自己的块表记录。

字典是一个容器对象,可以包含任何AutoCAD对象或 XRecord 。字典存储在数据库中的命名对象字典下,或者作为表记录或图形实体的扩展字典。命名对象字典是与数据库关联的所有字典的主表。与符号表不同,可以创建新字典并将其添加到命名对象字典中。

注意:字典对象不能包含图形图元。

VBA/ActiveX交叉引用

AutoCAD .NET API中的 Database 对象类似于ActiveX Automation库中的 Document 对象。要访问ActiveX Automation库的 Document 对象中可用的大多数特性,您需要使用AutoCAD .NET API的Document和Database对象。

img

图形和非图形对象(.NET)

图形对象(也称为实体)是构成图形的可见对象(直线、圆、光栅图像等)。将图形对象添加到图形的方法是:参照正确的块表记录,然后使用带有新对象的 AppendEntity 方法将其追加到图形。

若要修改或查询对象,请从相应的块表记录中获取对象的引用,然后使用对象本身的方法或特性。每个图形对象都具有执行与AutoCAD编辑命令(如“复制”、“缩放”、“移动”、“镜像”等)相同功能的方法。

这些对象还具有检索扩展数据(扩展数据)、高亮显示和取消高亮显示以及设置其他图元的属性的方法。大多数图形对象都有一些共同的属性,例如 LayerId 、 LinetypeId 、 Color 和 Handle 。每个图形对象还具有特定的属性,例如 Center 、 StartPoint 、 Radius 和 FitTolerance 。

非图形对象是图形中不可见的(信息性)对象,例如图层、线型、标注样式、表格样式等。要创建新的符号表记录,请使用所有者表上的 Add 方法或使用 SetAt 方法将字典添加到命名对象字典。若要修改或查询这些对象,请使用对象本身的方法或属性。每个非图形对象都具有特定于其用途的方法和属性;所有对象都具有检索扩展数据(扩展数据)和擦除自身的方法。

集合对象(.NET)

AutoCAD将大多数图形和非图形对象分组到集合或容器对象中。虽然集合包含不同类型的数据,但可以使用类似的技术处理它们。每个集合都有一个向集合中添加对象或从集合中获取项的方法。大多数集合使用 Add 或 SetAt 方法将对象添加到集合中。

大多数集合都提供类似的方法和属性,使它们易于使用和学习。 Count 属性返回集合中对象的计数,从零开始,而Item函数返回集合中的对象。AutoCAD .NET API中集合成员的示例包括:

  • 图层符号表中的图层表记录
  • ACAD_LAYOUT字典中的布局
  • DocumentCollection中的文档
  • 块参照中的属性

非原生图形和非图形对象(.NET)

AutoCAD .NET API是ObjectARX和ActiveX Automation的交叉实现。虽然可以从ObjectARX应用程序使用ActiveX Automation,但AutoCAD .NET API提供对ActiveX Automation库对象的直接访问。使用本机AutoCAD .NET API处理对象时,还可以从特性访问等效的COM对象。在某些情况下,COM对象是以编程方式访问AutoCAD要素的唯一方法。通过AutoCAD .NET API显示COM对象的特性的一些示例包括 Preferences 、 Menubar 、 MenuGroups 、 AcadObject 和 AcadApplication 。

注意:使用COM对象时,您需要确保引用AutoCAD类型库。

应用程序对象的 Preferences 属性提供对一组COM对象的访问,每个对象对应于“选项”对话框中的一个选项卡。这些对象一起提供了对“选项”对话框中所有注册表存储的设置的访问。还可以使用 Application 对象的 SetSystemVariable 和 GetSystemVariable 方法设置和修改选项(以及不属于“选项”对话框的系统变量)。

如果您正在使用可能最初为VB或VBA开发的现有代码,或者甚至在使用可能与AutoCAD ActiveX Automation库和AutoCAD .NET API一起使用的第三方库时,COM对象非常有用。与 Preferences 对象一样,您还可以使用 Utility 对象访问转换坐标或基于角度和距离定义新点的实用程序,该对象可以从 AcadApplication COM对象访问,该对象相当于AutoCAD中的 Application 对象。NET API。

注意:同时使用AutoCAD .NET API和ActiveX Automation时,如果您创建了可能需要返回对象的自定义函数,建议返回 ObjectId 而不是对象本身。

访问对象层次结构(.NET)

虽然Application是AutoCAD .NET API中的根对象,但您通常将使用当前图形的数据库。 Application 对象的 DocumentManager 属性允许您使用 MdiActiveDocument 属性访问当前文档。从由 MdiActiveDocument 属性返回的 Document 对象,您可以使用 Database 属性访问其数据库。

1
Application.DocumentManager.MdiActiveDocument.Database.Clayer;

本节中的主题

  • 引用对象层次结构(.NET)中的对象
  • 访问应用程序对象(.NET)

引用对象层次结构(.NET)中的对象

在AutoCAD .NET API中使用对象时,可以直接引用某些对象,也可以通过基于所使用对象的用户定义变量来引用某些对象。若要直接引用对象,请将该对象包含在调用层次结构中。例如,以下语句将图形文件附加到当前图形的数据库。请注意,层次结构从Application开始,然后转到 Database 对象。从 Database 对象中调用 方法:

1
2
3
4
5
6
7
string strFName, strBlkName;
Autodesk.AutoCAD.DatabaseServices.ObjectId objId;

strFName = "c:/clients/Proj 123/grid.dwg";
strBlkName = System.IO.Path.GetFileNameWithoutExtension(strFName);

objId = Application.DocumentManager.MdiActiveDocument.Database.AttachXref(strFName, strBlkName);

要通过用户定义的变量引用对象,请将变量定义为所需的类型,然后将变量设置为适当的对象。例如,以下代码定义了一个类型为 Autodesk.AutoCAD.DatabaseServices.Database 的变量( acCurDb ),并将该变量设置为等于当前数据库:

1
2
Autodesk.AutoCAD.DatabaseServices.Database acCurDb;
acCurDb = Application.DocumentManager.MdiActiveDocument.Database;

然后,以下语句使用 acCurDb 用户定义变量将图形文件附着到数据库:

1
2
3
4
5
6
7
string strFName, strBlkName;
Autodesk.AutoCAD.DatabaseServices.ObjectId objId;

strFName = "c:/clients/Proj 123/grid.dwg";
strBlkName = System.IO.Path.GetFileNameWithoutExtension(strFName);

objId = acCurDb.AttachXref(strFName, strBlkName);

从模型空间中检索图元

下面的示例返回模型空间中的第一个实体对象。类似的代码可以对图纸空间图元执行相同的操作。请注意,所有图形对象都定义为 Entity 对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;

[CommandMethod("ListEntities")]
public static void ListEntities()
{
// Get the current document and database, and start a transaction
Document acDoc = Application.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;

using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
{
// Open the Block table record for read
BlockTable acBlkTbl;
acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId,
OpenMode.ForRead) as BlockTable;

// Open the Block table record Model space for read
BlockTableRecord acBlkTblRec;
acBlkTblRec = acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace],
OpenMode.ForRead) as BlockTableRecord;

int nCnt = 0;
acDoc.Editor.WriteMessage("\nModel space objects: ");

// Step through each object in Model space and
// display the type of object found
foreach (ObjectId acObjId in acBlkTblRec)
{
acDoc.Editor.WriteMessage("\n" + acObjId.ObjectClass.DxfName);

nCnt = nCnt + 1;
}

// If no objects are found then display a message
if (nCnt == 0)
{
acDoc.Editor.WriteMessage("\n No objects found");
}

// Dispose of the transaction
}
}

访问Application对象(.NET)

Application对象位于对象层次的根,它提供对AutoCAD主窗口的访问。例如,下面的代码行更新应用程序:

1
Autodesk.AutoCAD.ApplicationServices.Application.UpdateScreen();

集合对象(.NET)

集合是一种包含许多类似对象实例的对象类型。以下列表包含AutoCAD .NET API中的一些集合对象:

Block Table Record
包含特定块定义中的所有图元。

Block Table
包含图形中的所有块。

Named Objects Dictionary
包含图形中的所有词典。

Dimension Style Table
包含图形中的所有标注样式。

Document Collection
包含当前任务中所有打开的图形。

Group Dictionary
包含图形中的所有编组。

Hyperlink Collection
包含给定实体的所有超链接。

Layer Table
包含图形中的所有图层。

Layout Dictionary
包含图形中的所有布局。

Linetype Table
包含图形中的所有线型。

MenuBar Collection
包含当前在AutoCAD中显示的所有菜单。

MenuGroup Collection
包含AutoCAD中当前加载的所有自定义组。自定义组表示加载的CUIx文件,该文件可以包含菜单、菜单和功能区选项卡以及定义用户界面的其他元素。

Plot Configuration Dictionary
包含图形中的命名打印设置。

Registered Application Table
包含图形中所有注册的应用程序。

Text Style Table
包含图形中的所有文字样式。

UCS Table
包含图形中的所有用户坐标系(UCS)。

View Table
包含图形中的所有视图。

Viewport Table
包含图形中的所有视口。

本节中的主题

  • 访问集合(.NET)
  • 向集合对象添加新成员(.NET)
  • 遍历集合对象(.NET)
  • 创建集合对象的成员(.NET)

访问集合(.NET)

大多数集合和容器对象都是通过 Document 或 Database 对象访问的。 Document 和 Database 对象包含一个属性,用于访问大多数可用Collection对象的对象或对象ID。例如,以下代码定义变量并检索表示当前图形中 Layers 集合的 LayersTable 对象:

1
2
3
4
5
6
7
8
9
10
11
// Get the current document and start the Transaction Manager
Database acCurDb = Application.DocumentManager.MdiActiveDocument.Database;
using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
{
// This example returns the layer table for the current database
LayerTable acLyrTbl;
acLyrTbl = acTrans.GetObject(acCurDb.LayerTableId,
OpenMode.ForRead) as LayerTable;

// Dispose of the transaction
}

向集合对象添加新成员(.NET)

要向集合中添加新成员,请使用 Add 方法。例如,以下代码创建一个新层并将其添加到“层”(Layer)表中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;

[CommandMethod("AddMyLayer")]
public static void AddMyLayer()
{
// Get the current document and database, and start a transaction
Document acDoc = Application.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;

using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
{
// Returns the layer table for the current database
LayerTable acLyrTbl;
acLyrTbl = acTrans.GetObject(acCurDb.LayerTableId,
OpenMode.ForRead) as LayerTable;

// Check to see if MyLayer exists in the Layer table
if (acLyrTbl.Has("MyLayer") != true)
{
// Open the Layer Table for write
acTrans.GetObject(acCurDb.LayerTableId, OpenMode.ForWrite);

// Create a new layer table record and name the layer "MyLayer"
using (LayerTableRecord acLyrTblRec = new LayerTableRecord())
{
acLyrTblRec.Name = "MyLayer";

// Add the new layer table record to the layer table and the transaction
acLyrTbl.Add(acLyrTblRec);
acTrans.AddNewlyCreatedDBObject(acLyrTblRec, true);
}

// Commit the changes
acTrans.Commit();
}

// Dispose of the transaction
}
}

遍历集合对象(.NET)

要选择Collection对象的特定成员,请使用 Item 或 GetAt 方法。 Item 和 GetAt 方法需要一个字符串形式的键,其中表示项的名称。对于大多数集合,Item方法是隐含的,这意味着您实际上不需要使用方法。

对于某些Collection对象,您还可以使用索引号来指定要检索的项在集合中的位置。您可以使用的方法根据您使用的语言以及使用符号表或字典而有所不同。

以下语句显示如何访问图层符号表中的“MyLayer”表记录。

1
acObjId = acLyrTbl["MyLayer"];

遍历LayerTable对象

以下示例遍历 LayerTable 对象并显示其所有图层表记录的名称:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;

[CommandMethod("IterateLayers")]
public static void IterateLayers()
{
// Get the current document and database, and start a transaction
Document acDoc = Application.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;

using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
{
// This example returns the layer table for the current database
LayerTable acLyrTbl;
acLyrTbl = acTrans.GetObject(acCurDb.LayerTableId,
OpenMode.ForRead) as LayerTable;

// Step through the Layer table and print each layer name
foreach (ObjectId acObjId in acLyrTbl)
{
LayerTableRecord acLyrTblRec;
acLyrTblRec = acTrans.GetObject(acObjId,
OpenMode.ForRead) as LayerTableRecord;

acDoc.Editor.WriteMessage("\n" + acLyrTblRec.Name);
}

// Dispose of the transaction
}
}

在LayerTable对象中查找名为MyLayer的图层表记录

以下示例检查 LayerTable 对象以确定名为MyLayer的图层是否存在,并显示相应的消息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;

[CommandMethod("FindMyLayer")]
public static void FindMyLayer()
{
// Get the current document and database, and start a transaction
Document acDoc = Application.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;

using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
{
// Returns the layer table for the current database
LayerTable acLyrTbl;
acLyrTbl = acTrans.GetObject(acCurDb.LayerTableId,
OpenMode.ForRead) as LayerTable;

// Check to see if MyLayer exists in the Layer table
if (acLyrTbl.Has("MyLayer") != true)
{
acDoc.Editor.WriteMessage("\n'MyLayer' does not exist");
}
else
{
acDoc.Editor.WriteMessage("\n'MyLayer' exists");
}

// Dispose of the transaction
}
}

擦除集合对象的成员(.NET)

可以使用成员对象上的 Erase 方法删除集合对象中的成员。例如,下面的代码从 LayerTable 对象中擦除图层MyLayer。

在从图形中删除图层之前,应确保可以安全地删除该图层。若要确定是否可以擦除图层或其他命名对象(如块或文字样式),应使用 Purge 方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;

[CommandMethod("RemoveMyLayer")]
public static void RemoveMyLayer()
{
// Get the current document and database, and start a transaction
Document acDoc = Application.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;

using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
{
// Returns the layer table for the current database
LayerTable acLyrTbl;
acLyrTbl = acTrans.GetObject(acCurDb.LayerTableId,
OpenMode.ForRead) as LayerTable;

// Check to see if MyLayer exists in the Layer table
if (acLyrTbl.Has("MyLayer") == true)
{
LayerTableRecord acLyrTblRec;
acLyrTblRec = acTrans.GetObject(acLyrTbl["MyLayer"],
OpenMode.ForWrite) as LayerTableRecord;

try
{
acLyrTblRec.Erase();
acDoc.Editor.WriteMessage("\n'MyLayer' was erased");

// Commit the changes
acTrans.Commit();
}
catch
{
acDoc.Editor.WriteMessage("\n'MyLayer' could not be erased");
}
}
else
{
acDoc.Editor.WriteMessage("\n'MyLayer' does not exist");
}

// Dispose of the transaction
}
}

一旦对象被擦除,以后就不应该在程序中再次尝试访问该对象;否则将发生错误。上面的示例测试在再次访问对象之前查看对象是否存在。当请求删除一个对象时,你应该使用 Has 方法检查该对象是否存在,或者使用 Try 语句来捕获任何发生的异常。

了解属性和方法(.NET)

每个对象都有关联的属性和方法。属性描述单个对象的各个方面,而方法是可以在单个对象上执行的操作。创建对象后,可以通过其属性和方法查询和编辑对象。

例如,Circle对象具有 Center 属性。此属性表示世界坐标系(WCS)中位于该圆中心的点。要更改圆心,只需将 Center 属性设置为新点。 Circle 对象也有一个名为 GetOffsetCurves 的方法。此方法在距现有圆的指定偏移距离处创建新对象。

若要查看 Circle 对象的所有属性和方法的列表,请参阅 Circle 对象参考主题或使用Microsoft® Visual Studio®中的对象浏览器。

进程外与进程内(.NET)

当你开发一个新的应用程序时,它可以在进程内运行,也可以在进程外运行。AutoCAD .NET API设计为仅在进程内运行,这与可在进程内或进程外使用的ActiveX Automation库不同。

  • 进程内应用程序被设计为在与宿主应用程序相同的进程空间中运行。在这种情况下,DLL程序集将加载到宿主应用程序AutoCAD中。
  • 进程外应用程序不与宿主应用程序在同一空间中运行。这些应用程序通常构建为独立的可执行文件。

如果需要创建独立应用程序来驱动AutoCAD,最好创建一个使用 CreateObject 和 GetObject 方法的应用程序,以创建AutoCAD应用程序的新实例或返回当前正在运行的实例之一。返回对 AcadApplication 的引用后,可以使用 SendCommand 方法将进程内.NET应用程序加载到AutoCAD中,该方法是 AcadApplication 的 ActiveDocument 属性的成员。

作为在进程内执行.NET应用程序的替代方法,可以为应用程序使用COM互操作。

注意:COM应用程序访问AutoCAD 2024的ProgID为AutoCAD.Application.24.3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
using System;
using System.Runtime.InteropServices;

using Autodesk.AutoCAD.Interop;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;

[CommandMethod("ConnectToAcad")]
public static void ConnectToAcad()
{

AcadApplication acAppComObj = null;
const string strProgId = "AutoCAD.Application.24.3";

// Get a running instance of AutoCAD
try
{
acAppComObj = (AcadApplication)Marshal.GetActiveObject(strProgId);
}
catch // An error occurs if no instance is running
{
try
{
// Create a new instance of AutoCAD
acAppComObj = (AcadApplication)Activator.CreateInstance(Type.GetTypeFromProgID(strProgId), true);
}
catch
{
// If an instance of AutoCAD is not created then message and exit
System.Windows.Forms.MessageBox.Show("Instance of 'AutoCAD.Application'" +
" could not be created.");

return;
}
}

// Display the application and return the name and version
acAppComObj.Visible = true;
System.Windows.Forms.MessageBox.Show("Now running " + acAppComObj.Name +
" version " + acAppComObj.Version);

// Get the active document
AcadDocument acDocComObj;
acDocComObj = acAppComObj.ActiveDocument;

// Optionally, load your assembly and start your command or if your assembly
// is demandloaded, simply start the command of your in-process assembly.
acDocComObj.SendCommand("(command " + (char)34 + "NETLOAD" + (char)34 + " " +
(char)34 + "c:/myapps/mycommands.dll" + (char)34 + ") ");

acDocComObj.SendCommand("MyCommand ");
}

定义命令和AutoLISP函数(.NET)

可以使用AutoCAD .NET API通过使用两个属性( CommandMethod 和 LispFunction )来定义命令和AutoLISP®函数。在AutoCAD中执行命令或AutoLISP函数时,将两个特性之一放置在应调用的方法之前。

用于命令的方法不应使用参数定义。但是,用于定义AutoLISP函数的方法应使用 ResultBuffer 对象类型的单个参数进行定义。

Topics in this section 本节中的主题

  • 命令定义(.NET)
  • AutoLISP函数定义(.NET)

命令定义(.NET)

定义命令时,使用 CommandMethod 属性。 CommandMethod 属性需要一个字符串值作为正在定义的命令的全局名称。沿着全局命令名, CommandMethod 属性可以接受以下值:

  • 命令标志-定义命令的行为
  • Group Name-命令组名称
  • 本地名称-本地命令名称,通常是特定于语言的
  • Help Topic Name-按F1时应显示的帮助主题名称
  • 上下文菜单类型标志-定义命令激活时的上下文菜单行为
  • Help File Name-包含帮助主题的帮助文件,当命令处于活动状态并按下F1键时,将显示该帮助主题

下表列出了可用于定义命令行为的可用标志。

枚举值 描述
ActionMacro 命令可以用动作录制器录制为动作。
Defun 命令可以作为LISP函数调用,因此可以使用 acedGetArgs() 从LISP接收参数,并可以使用 acedRetXxx() 函数将值返回到LISP。此标志只能由Visual LISP引擎设置。
DocExclusiveLock 当命令被调用时,文档将被独占锁定。
DocReadLock 当命令被调用时,文档将被读锁定。
Interruptible 当提示用户输入时,命令可能会中断。
Modal 当另一个命令处于活动状态时,无法调用该命令。
NoActionRecording 命令不能用动作录制器录制为动作。
NoBlockEditor 不能从块编辑器中使用命令。
NoHistory 命令未添加到repeat-last-command历史记录列表。
NoInferConstraint 推断约束时不能使用命令。
NoInternalLock 文档不能内部锁定。
NoMultiple 命令宏中带有星号(*)前缀时,命令不支持多重行为。
NoNewStack 命令不在堆栈上创建新项。
NoOEM 无法从AutoCAD OEM访问命令。
NoPaperSpace 不能从图纸空间使用命令。
NoPerspective 当PERSPECTIVE设置为1时,无法使用命令。
NoTileMode 当TILEMODE设置为1时,无法使用命令。
NoUndoMarker 命令不支持撤消标记。这适用于不修改数据库的命令,因此不应显示在撤消文件中。
Redraw 检索优先拾取集或夹点集时,不会清除它们。
Session 命令在应用程序的上下文中而不是在当前文档上下文中执行。
TempShowDynDimension 命令允许在选定图元时临时显示动态尺寸。
Transparent 命令可以在另一个命令处于活动状态时使用。
Undefined 命令只能通过其全局名称使用。
UsePickSet 检索到优先拾取集时,将清除该集。

实例和静态命令方法

命令方法可以声明为实例方法或静态方法。静态命令方法在C#中使用static关键字声明,在VB. NET中使用 Shared 关键字声明。实例命令方法是不使用static或 Shared 关键字声明的公共类成员。

对于实例命令方法,方法的封闭类型为每个打开的文档单独实例化。这意味着每个文档都获得命令实例数据的私有副本。因此,当用户切换文档时,不存在丢失特定于文档的数据的危险。如果一个实例方法需要全局共享数据,它可以通过声明static或Shared成员变量来实现。

对于静态命令方法,托管包装运行时模块不需要实例化封闭类型。无论文档上下文如何,都使用方法数据的单个副本。静态命令通常不使用每个文档的数据,也不需要特别考虑MDI模式。

实例和静态方法可以用命令标志来定义,以适应特殊要求。例如,一个实例方法可以用一个设置 CommandFlags.Session 标志的属性来声明。这意味着该命令在应用程序执行上下文中运行,但也维护每个文档的数据。此类命令的AutoCAD示例是PROPERTIES命令。

同样地,静态方法可以在没有 CommandFlags.Session 标志的情况下声明。这种组合对于在文档上下文中运行但不需要维护每个文档数据的命令很有用。

定义命令的语法

下面演示了如何创建一个 CommandMethod 属性,该属性定义了一个名为CheckForPickfirstSelection的命令。该属性还使用命令标志 UsePickSet 来指示允许命令使用在命令启动之前选择的对象。

1
2
3
4
5
[CommandMethod("CheckForPickfirstSelection", CommandFlags.UsePickSet)]
public static void CheckForPickfirstSelection()
{
. . .
}

可以通过在VB.NET中使用“+”运算符和C#中的“|”操作符。

1
2
3
4
5
6
[CommandMethod("CheckForPickfirstSelection", CommandFlags.UsePickSet |
CommandFlags.NoBlockEditor)]
public static void CheckForPickfirstSelection()
{
. . .
}

AutoLISP函数定义(.NET)

定义AutoLISP函数时,使用 LispFunction 属性。 LispFunction 属性需要一个字符串值,用作所定义AutoLISP函数的全局名称。沿着全局函数名, LispFunction 结构可以接受以下值:

  • 本地名称-本地函数名,通常是特定于语言的
  • Help Topic Name-应与AutoLISP函数关联的帮助主题名称
  • Help File Name-包含帮助主题的帮助文件,当命令处于活动状态并按下F1键时,将显示该帮助主题

定义AutoLISP函数的命令

下面演示如何创建一个 LispFunction 属性,该属性定义名为InsertDynamicBlock的AutoLISP函数。

1
2
3
4
5
[LispFunction("DisplayFullName")]
public static void DisplayFullName(ResultBuffer rbArgs)
{
. . .
}

传递给AutoLISP函数的值

使用 Foreach 循环遍历AutoLISP函数在 ResultBuffer 中返回的值。 ResultBuffer 是 TypedValue 对象的集合。 TypedValue 对象的 TypeCode 属性可用于确定传递到AutoLISP函数中的每个值的值类型。 Value 属性用于返回 TypedValue 对象的值。

支持的数据类型包括:

  • Boolean or bool
  • Double or double
  • Integer or int
  • Null or void
  • ObjectId
  • Point2d
  • Point3d
  • ResultBuffer
  • SelectionSet
  • String or string
  • TypedValue

定义AutoLISP函数的步骤

此示例代码定义名为 DisplayFullName 的AutoLISP函数。虽然.NET项目中定义的方法接受单个值,但AutoLISP函数需要两个字符串值来生成正确的输出。

将.NET项目加载到AutoCAD中,然后在命令提示下输入以下命令:

1
(displayfullname "First" "Last")

以下是执行AutoLISP函数后显示的输出:

1
Name: First Last
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;

[LispFunction("DisplayFullName")]
public static void DisplayFullName(ResultBuffer rbArgs)
{
if (rbArgs != null)
{
string strVal1 = "";
string strVal2 = "";

int nCnt = 0;
foreach (TypedValue rb in rbArgs)
{
if (rb.TypeCode == (int)Autodesk.AutoCAD.Runtime.LispDataType.Text)
{
switch(nCnt)
{
case 0:
strVal1 = rb.Value.ToString();
break;
case 1:
strVal2 = rb.Value.ToString();
break;
}

nCnt = nCnt + 1;
}
}

Application.DocumentManager.MdiActiveDocument.Editor.
WriteMessage("\nName: " + strVal1 + " " + strVal2);
}
}

注:翻译自ObjectARX: Managed .NET Developer’s Guide,且只保留了C#部分的代码