Sei sulla pagina 1di 20

12/3/2008 - 10:15 am - 11:45 am Room:San Polo 3404 (MSD)

AutoCAD .NET Basics


Stephen Preston - Americas Manager, Developer Technical Services, Autodesk

DE205-4

Wondering what all the hype is around .NET? We'll give you the basic information you need to get up to speed on writing your own .NET applications based on the AutoCAD .NET application programming interface (API). This foundation class includes: an overview of the .NET Framework and what is means for programmers; how to write your first AutoCAD .NET add-in; simple user interaction; a discussion of the structure of the DWG database; how to add CAD entities to the DWG database; and how to traverse the entities already in the DWG. Make sure you also sign up for our "AutoCAD .NET: A Tour" class if you attend this.

About the Speaker: Stephen has been a member of the Autodesk Developer Technical Services Team since 2000, first as a support engineer and then as manager of the EMEA (Europe, Middle East, and Africa) Team. In those roles, his responsibilities included support for the AutoCAD APIs, including ObjectARX and AutoCAD .NET, as well as AutoCAD OEM and RealDWG technologies. Currently, he manages the Developer Technical Services Team in the Americas and serves as Workgroup Lead, working closely with the AutoCAD engineering team on future improvements in the AutoCAD APIs. Stephen started his career as a scientist, and has a Ph.D in Atomic and Laser Physics from the University of Oxford.

Stay Connect with AU all year at www.autodeskuniversity.com

DE205-4: AutoCAD .NET Basics

AutoCAD .NET Basics


What this seminar is (and what it isnt)
AutoCAD .NET Basics is an introduction to the AutoCAD .NET API. The class is intended to form a foundation for the other .NET seminars being delivered by the Autodesk Developer Network team. These are: DE305-3 AutoCAD .NET: A Tour DE315-2 AutoCAD .NET: Developing a User Interface DE401-1 AutoCAD .NET: Using .NET with your LISP Applications This is not a beginners class on programming. The seminar assumes that you have a basic understanding of simple programming concepts (including the basics of .NET programming), and that you are familiar with AutoCAD. It is assumed that you have never before used the AutoCAD .NET API1. If youve never programmed before, then youre probably better signing up for a hands on class to get you started. Or sign up for DE305-3 AutoCAD .NET: A Tour if you want a high-altitude fly-past of the capabilities of the AutoCAD .NET API.

A very brief history of the AutoCAD.NET API


The first version of the AutoCAD .NET API (sometimes called ObjectARX .NET or Managed ObjectARX) was released with AutoCAD 2005. Before then, use of the .NET Framework with AutoCAD was restricted to automating AutoCAD from an external .NET application through COM Interop. Using COM Interop is really just using .NET as a glorified VB6 application, and is very different from native .NET programming. The AutoCAD 2005 .NET API was a preview version. It did include the classes required to access the DWG Database and all the objects in that Database, but the editor (or non-DWGrelated) API was very limited - only allowing the creation of very simple commands. AutoCAD 2006 saw the release of the first full AutoCAD .NET API, and there were a few architectural changes to allow greater flexibility. The main change was the introduction of Transactions as the primary means of modifying the DWG Database. (The 2005 API relied on the Open/Close model favored by ObjectARX2 programmers). The 2006 API release completed the DWG Database access functionality (adding a few classes for AutoCAD entities that were
1

A note to beginners API means Application Programming Interface. Thats the set of functions AutoCAD exposes for you to use in your application to make AutoCAD do what you want.

The AutoCAD .NET API is a wrapper on top of the (unmanaged) C++ ObjectARX API. ObjectARX programmers have a big advantage over VB or LISP programmers, because the AutoCAD .NET Object Model is based on ObjectARX.

DE205-4: AutoCAD .NET Basics

missing from the 2005 release), and adding lots of Editor functionality (such as InputPointMonitors, SelectionSets, advanced command line interaction, etc.) and a comprehensive Event model. Since the AutoCAD 2006 release, the .NET API architecture has remained unchanged. Changes since then have been in adding new APIs corresponding to new product features. In fact, some AutoCAD APIs (the CUI API, for example) are only available as .NET APIs. However, the 2007 API did take advantage of AutoCAD 2007 being a binary incompatible release to move from .NET Framework 1.1 to .NET Framework 2. As the API now uses features introduced in Framework 2, it is no longer possible to develop AutoCAD .NET applications using an IDE that relies on older .NET Frameworks3.

A Hello World tutorial


As youre really keen to learn the AutoCAD .NET API, youll have picked up this handout when you arrived at AU, and youre now sitting in your hotel room with your laptop, ready to fire up Visual Studio 20054 to get ahead of the game before the seminar. So go on then double-click that squirly icon and get programming. You know you want to!

If youve ever been subjected to a learn to program tutorial before, youll know that every beginners tutorial in the world starts with a Hello World project. So who are we to break with decades of tradition? Once Visual Studio has started, you need to create a new project. Go to the File menu and select New->Project.

Unsurprisingly, this displays the New Project dialog. Were going to create a small VB.NET project. The steps are pretty much the same for C#; its just the C# syntax around the AutoCAD API calls that differs. Well show a C# project in the class.
3
4

. For Visual Studio, this means version 2005 or higher is needed.

You dont have to buy Visual Studio to write your AutoCAD .NET add-ins. There are a number of free development environments available. For example, you can use Visual Studio Express, but you have to tweak it a little to get it to work see Kean Walmsleys blog posting for details (http://through-theinterface.typepad.com/through_the_interface/2006/07/debugging_using.html).

DE205-4: AutoCAD .NET Basics

Click on the Visual Basic project type and select the Class Library Template. Then give the project a name. You can call it anything you like, but (being a slave to tradition) Im going to call it HelloWorld.

When youve done that, click OK. Now open the Solution Explorer window (the View->Solution Explorer menu item) if its not already open; double click on My Project; and select the References tab.

DE205-4: AutoCAD .NET Basics

Click the Add button, select the Browse tab; navigate to C:\Program Files\AutoCAD 2009 (or wherever your AutoCAD is installed), and search for *mgd.dll (i.e. type *mgd.dll in the File name textbox and click OK).

This will display all the files in that folder ending with mgd.dll. Now select acmgd.dll and acdbmgd.dll by Ctrl-clicking on them both; then click OK. These are the two DLLs that expose the AutoCAD .NET API. acmgd.dll exposes all the Editor functionality (SelectionSets, Commands and Keywords, Prompts and Dialogs, etc.); acdbmgd.dll exposes all the Database access functionality (the DWG Database itself, Lines, Circles, MText, etc.).

DE205-4: AutoCAD .NET Basics

Back on the My Project screen References tab, double-click on acdbmgd.dll to display its Properties, and set Copy Local to False. (This is to ensure your .NET add-in loads the copy of acdbmgd.dll stored in the AutoCAD folder and doesnt try to make and load a local copy. You probably guessed that from the property name). Then do the same for acmgd.dll.

Now we want to write our code. Double-click on Class1.vb in the Solution Explorer window. This is where you write your add-in code. Edit the template code as follows:

Imports Autodesk.AutoCAD.Runtime Imports Autodesk.AutoCAD.ApplicationServices Imports Autodesk.AutoCAD.DatabaseServices

Public Class Class1 <CommandMethod("HelloWorld")> _ Public Sub MyMethod() Application.ShowAlertDialog("Hello World from VB.NET!") End Sub End Class

The Imports statements allow you to use classes from the namespaces you import without having to type out the full namespace. You dont strictly need them, but the code becomes hard to read otherwise. For example,
Application.ShowAlertDialog("Hello World from VB.NET!")

becomes

DE205-4: AutoCAD .NET Basics

Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("Hello World from VB.NET!")

There are several other Autodesk.AutoCAD namespaces, but these are the three youll need in just about every AutoCAD add-in you write. (In this example, DatabaseServices is not strictly necessary).
<CommandMethod("HelloWorld")> is an attribute. This is telling AutoCAD to run the

subroutine MyMethod when the user types HELLOWORLD on the command line. The rest of the code should be self-explanatory. Thats all the code we need. But before we can test our first AutoCAD add-in we have to set one more project setting. Double-click again on My Project in the Solution Explorer; select the Debug tab; set the Start Action to Start external program; and enter the location of the AutoCAD executable the default location is C:\Program Files\AutoCAD 2009\acad.exe. This is telling Visual Studio that youre going to load your DLL into the AutoCAD process space to debug it5.

Now were ready to run our add-in. Hit F5 to start debugging, and AutoCAD will launch. Type NETLOAD on the command line and hit ENTER. In the NETLOAD file select dialog, navigate to the location of your compiled .NET assembly DLL. This should be in this location, unless you changed your default project settings:

The AutoCAD .NET API can only be used from inside the AutoCAD process space. You cant use admgd.dll and acdbmgd.dll in a standalone executable. (But see the section on RealDWG at the end of this document).

DE205-4: AutoCAD .NET Basics

The assembly DLL is called HelloWorld.dll. Double-click on it to load it. Now type HELLOWORLD at the command line, and AutoCAD will display this dialog.

Congratulations! Youve just created your first custom command using AutoCAD .NET.

But lets not stop just yet. Switch back to Visual Studio and hit Shift+F5 to stop the debugging session, open up Class1.vb by double-clicking on it in the Solution Explorer, and replace all the code in that document with this:
Imports Autodesk.AutoCAD.Runtime Imports Autodesk.AutoCAD.ApplicationServices Imports Autodesk.AutoCAD.DatabaseServices Public Class Class1 <CommandMethod("HelloWorld")> _ Public Sub MyMethod() ' Some variable definitions Dim activeDoc As Document Dim BTR As BlockTableRecord ' Store a reference to the currently active document (to make the next two lines of code shorter) activeDoc = Application.DocumentManager.MdiActiveDocument ' Start a transaction to edit the DWG database Using trans As Transaction = activeDoc.TransactionManager.StartTransaction() ' Open BlockTableRecord of currently active space ready to add entity. ' (This will be ModelSpace if you've not switched to a layout, otherwise PaperSpace). BTR = trans.GetObject(activeDoc.Database.CurrentSpaceId, OpenMode.ForWrite) ' Create a new MText entity and set its text Dim txt As MText = New MText txt.Contents = "Hello World from VB.NET!" ' Add the MText to ModelSpace BTR.AppendEntity(txt) txt.SetDatabaseDefaults()

DE205-4: AutoCAD .NET Basics

' Add the Mtext to the transaction trans.AddNewlyCreatedDBObject(txt, True) ' Commit transaction so changes persist in the DWG Database. trans.Commit() End Using End Sub End Class

Now hit F5 again; NETLOAD the HelloWorld.dll; and invoke the HELLOWORLD command again. ZOOM EXTENTS and you should see this:

Give yourself a big hug youve just created your first drawing using VB.NET!

The DWG Database format


So now weve worked through the ubiquitous Hello World tutorial. We ended up waving a magic wand to add some MText to ModelSpace. That was our first glimpse of the DWG Database structure, which is the most important part of the AutoCAD .NET object model to learn. You will never understand the ObjectARX or AutoCAD .NET API until you understand the DWG Database structure. Its as simple as that. So lets take a look at it now. The DWG Database is not that different to any other database (an MS Access database, for example). If youve ever done any database programming, then youre halfway there already. 10

DE205-4: AutoCAD .NET Basics

Like any database, the DWG Database consists of a number of tables in which are stored records. For example, an MS Access database might contain a table of employees (lets call it the EmployeeTable), which might contain a record for each Employee (an EmployeeTableRecord). Like this -

In the same way, most of the information in a DWG Database is stored in SymbolTables as SymbolTableRecords. We have several types of Symbol in AutoCAD, such as Blocks, Dimension Styles, Layers, LineTypes, UCSs, Views, Viewports, and Registered Applications (used for storing Xdata). Each of these SymbolTables stores a different type of SymbolTableRecord. The most important aspect of a CAD application is to be able to draw something, so lets concentrate on how AutoCAD stores its graphical Entities6 (Lines, Circles, Polylines, etc) you draw on-screen. Graphical Entities are always stored in (or are owned by) a BlockTableRecord. Think of a BlockTableRecord as containing all the Entities that make up the definition of a Block. But just to complicate things, ModelSpace and PaperSpace are also represented in the DWG Database by BlockTableRecords. This makes sense if you think about it - Block definitions and ModelSpace both just store a bunch of graphical Entities. The only difference is that you have a window to look into the ModelSpace and PaperSpace BlockTableRecords the drawing document. To view other BlockTableRecords, you have to insert a BlockReference into ModelSpace or PaperSpace. And, of course, all the BlockTableRecords are stored in the BlockTable. Below is a screenshot from the Inspector DWG Database viewing utility7, with the tree expanded to show some BlockTableRecords and LinetypeTableRecords. Note the names of the BlockTableRecords in the BlockTable shown on the left screenshot they include Model_Space and Paper_Space. The right-hand screenshot expands the ModelSpace BlockTableRecord to show the Entities it contains (two Lines, a Circle and a Polyline in this case). Dont worry about the AcDb prefix on the class names for now.

Entity has a special meaning in AutoCAD. This is the name given to anything in the DWG Database that is represented graphically. More generally, we use the word Object (or the DBObject class) to describe anything in the database that includes both Entities and non-graphical objects.
7

Available as an ObjectARX sample on the ADN website.

11

DE205-4: AutoCAD .NET Basics

Theres a little more to the DWG Database than just Tables. Notice the Named Objects Dictionary and Extension Dictionary shown in the Inspector tree. These are used for storing data in the DWG, but are outside the scope of this introductory class.

Transactions
Continuing with our database theme, it shouldnt come as a surprise that we have a similar mechanism for modifying the DWG Database as for modifying a relational database we use Transactions. The concept of a transaction is simple. Any changes you make within a transaction are only committed to the database when the transaction is committed. If anything goes wrong while youre modifying the database within a transaction, then you simply abort the transaction and the database is returned to the state it was in before the transaction started. This is shown in the simple flow diagram below.

12

DE205-4: AutoCAD .NET Basics

Unique Identifiers
As for any database, its very important to be able to identify each object stored in the DWG database. Without some kind of unique identifier, there would be no way to distinguish (for example) one red circle from the other red circles in the drawing. When you add an object to the DWG Database, it is assigned two unique identifiers a Handle and an ObjectID.

Handles
A Handle is unique within a drawing, but is not unique across all the drawings open in a session. This means that two objects in two different drawings can have the same Handle. (Although combining the Handle with the drawing pathname would be unique). Handles are saved with the drawing. When you save and reopen a drawing, each object will have the same handle as it did last time. The only time an objects handle will change is if you INSERT the object into a new drawing then the Handles have to change to avoid clashes with the Handles in the drawing youre INSERTing into. The .NET DBObject class the parent class for all objects that can be stored in the DWG database exposes a Handle property, which is inherited by all the classes that derive from it.

ObjectIds
Like a Handle, an ObjectId is unique within a drawing. But an ObjectId is also unique within an AutoCAD session. No matter how many drawings you open in one session, youll never see the same ObjectId. Unlike a Handle, the ObjectId isnt saved with the drawing, So when you close and reopen a drawing, the objects in it will most likely have different ObjectIds. AutoCAD uses ObjectIds to track relationships between objects in a drawing. But when AutoCAD saves these relationships in the DWG file, it translates them to handles. The DBObject class exposes an ObjectId property. You will mostly be using ObjectIds (rather than handles) in your .NET applications. The following table summarizes the similarities differences between Handles and ObjectIds. Handle Unique in DWG Unique in session Saved with DWG Yes No Yes ObjectId Yes Yes No

To find the ObjectId of an object you have the handle for, you can call the Database.GetObjectId() function. 13

DE205-4: AutoCAD .NET Basics

To find the Handle of an object you have an ObjectId for, you can open the object using its ObjectId and then call the DBObject.GetHandle() function.

Hello World again


Now weve covered the basics of the DWG Database structure, Transactions, and ObjectIds, lets walk through the code for the Hello World MText example we used earlier, starting just after the variable declarations in the function First we store a reference to the active document. This is just for convenience, so we dont have to write Application.DocumentManager.MdiActiveDocument twice.
activeDoc = Application.DocumentManager.MdiActiveDocument

Before we can access the Database, we have to start a new transaction. We start a transaction from the TransactionManager, which is accessed through a property of the Document.
Using trans As Transaction = activeDoc.TransactionManager.StartTransaction()

The Using keyword tells the .NET runtime to Dispose of the Transaction (trans) once the program flow has moved beyond the End Using statement. This just helps us to clean up after ourselves. (Otherwise, wed have to explicitly call the Transactions Dispose function when wed finished with it). To add an Entity to the currently active space (ModelSpace or PaperSpace), we ask the transaction to open the BlockTableRecord for the current space. We access the ObjectID of the current space using the CurrentSpaceId property of the Database, and pass it to the GetObject() method of the Transaction. Like in any database, we have a choice of opening the table for Write if were planning on adding or removing any records, or for Read if were only interested in querying the contents. In this case, were planning to add some Mtext to the BlockTableRecord, so we open it for Write.
BTR = trans.GetObject(activeDoc.Database.CurrentSpaceId, OpenMode.ForWrite)

There is an alternative to using the CurrentSpaceId property. Well mention it here for completeness, and because it ties in with our earlier discussion of the database structure To add an Entity to ModelSpace, we can work down the structure of the Database. First we need to access the Database for the currently active AutoCAD DWG document. Thats this line of code
DB = Application.DocumentManager.MdiActiveDocument.Database

14

DE205-4: AutoCAD .NET Basics

Next we open the BlockTable. We open it inside the transaction using the Transaction.GetObject() method. (The ObjectId for the BlockTable is returned by the BlockTableId property).
BT = trans.GetObject(DB.BlockTableId, OpenMode.ForRead)

Then we open the ModelSpace BlockTable Record (again using the transaction)
MS = trans.GetObject(BT(BlockTableRecord.ModelSpace),OpenMode.ForWrite)

This looks a bit funny, because the BlockTable class is a collection of BlockTableRecords. BlockTableRecord.ModelSpace is a pre-defined constant that returns the name of the ModelSpace BlockTableRecord. If wed wanted the BlockTableRecord defining Block_A, wed have called BT(Block_A). And notice that were opening the ModelSpace BlockTableRecord for Write thats because were planning on adding some MText to ModelSpace. Next we create a new instance of an MText Entity, set its contents to the text we want to display, and add it to the current space. The commented code is pretty obvious here. The SetDatabaseDefaults simply sets the textstyle etc. of the text to the default for this drawing.
' Create a new MText entity and set its text Dim txt As MText = New MText txt.Contents = "Hello World from VB.NET!" ' Add the MText to ModelSpace BTR.AppendEntity(txt) txt.SetDatabaseDefaults()

The next part isnt quite so obvious


' Add the MText to the transaction trans.AddNewlyCreatedDBObject(txt, True)

Weve created a new MText instance and added it to ModelSpace, so we need to let the Transaction know about that change. Thats how we can make sure the MText is removed from the Database if the Transaction is aborted, or permanently added if the Transaction is committed. You have to notify the Transaction like this every time you add something new to the DWG Database. Finally, we commit the Transaction. If we get to this line of code, then everything worked fine and there were no errors. Committing the Transaction makes our changes permanent and tidies up after us (closing everything that we opened).
' Commit transaction so changes persist in the DWG Database. trans.Commit()

By the way, Ive not put any error handling in this simple code. Error handling is a very important part of .NET, and we will cover that briefly in the seminar.

15

DE205-4: AutoCAD .NET Basics

Navigating the AutoCAD .NET Object Model


By now, youll be starting to grasp whats needed to add stuff to your drawings. The AutoCAD .NET API exposes a number of namespaces (some of which we touched on briefly already when we introduced the Imports keyword). These namespaces hold the classes you need to work with AutoCAD. Lets take a quick look at how you can find out the classes and functions available to you. Well focus here on the Autodesk.AutoCAD.DatabaseServices namespace, because (as its name suggests) thats the namespace that stores the .NET classes used to access the DWG Database. What follows assumes knowledge of basic Object-Oriented programming concepts8, particularly inheritance. A good way to view the classes available in a namespace is to use the Visual Studio Object Browser (the View->Object Browser menu item).

If you open the Object Browser for the Hello World application we created in our first handout (or any AutoCAD .NET add-in project), then you can expand the acdbmgd assembly to see the namespaces it contains.

Now expand the DatabaseServices namespace in the Object Browser, scroll down to the MText class and expand the tree below it as far as DBObject. Do the same with Line.

See (for example) http://en.wikipedia.org/wiki/Object-oriented_programming for an overview of this.

16

DE205-4: AutoCAD .NET Basics

Expanding the tree in this way exposes the inheritance hierarchy of that class9. We can see that MText is derived from (or is a type of) Entity, which in turn is derived from (or is a type of) DBObject. For a Line, we see that theres a further layer of abstraction. A Line is a type of Curve, which is a type of Entity, which is a type of DBObject. Arcs, Circles and Polylines (to name but a few) are also types of Curve. For our purposes, we can consider the base class for every object that can reside in a DWG Database to be DBObject. This means that anything you can access inside the DWG is derived from DBObject. There are other classes further up the hierarchy, but we dont normally work with those. Every DBObject in the Database that displays graphics is also an Entity10. How do you view the properties and events exposed by these classes? Click on MText, and youll see these listed to the right. Here weve scrolled down to show the Contents property we used in the sample code. Clicking on a method or property displays a function signature (as shown in the screenshot). If you now click on Entity in the expanded MText class node, youll see all the methods, properties and events that MText inherits from its parent Entity class (and that are common to every other class that is also a type of Entity).

Take some time to browse through and expand the different class nodes in the browser to see whats there. Here are the inheritance hierarchies for BlockTable and BlockTableRecord. You can see that BlockTable is a type of SymbolTable, and BlockTableRecord is a type of SymbolTableRecord as discussed earlier. Notice that these are not graphical entities, so theyre not a type of Entity. Look at the other Autodesk.AutoCAD namespaces as well and notice the different class hierarchies in those.
9

Object Browser shows a child to parent inheritance hierarchy. A parent to child diagram is better for studying which classes share common ancestors. The ObjectARX SDK includes such a diagram in the <ObjectARX SDK>\classmap folder. You could also define an Entity as anything that is owned by (or stored in) a BlockTableRecord.

10

17

DE205-4: AutoCAD .NET Basics

And a final note about the class names displayed by Inspector we showed earlier - The language of AutoCAD is ObjectARX. The .NET API is a thin wrapper on top of this. The classes in the DatabaseServices namespace are the same as those prefixed by AcDb in ObjectARX. So when you see AcDbLine in ObjectARX, this translates to Autodesk.AutoCAD.DatabaseServices.Line in .NET.

A note about RealDWG


RealDWG is a software development kit that allows you to create, modify or read a DWG file from your own standalone application. That means your application can work with the DWG format even without AutoCAD installed. RealDWG is used internally by all Autodesk applications, including AutoCAD itself. RealDWG includes a .NET API that is a subset of the full AutoCAD .NET API. Obviously, an API that works without requiring AutoCAD doesnt include any AutoCAD Editor specific functionality (e.g. viewing a drawing, defining commands, responding to mouse movements, creating SelectionSets, etc.), but it does include all of the AutoCAD .NET API needed to directly access the DWG Database from a standalone application. Thats the Autodesk.AutoCAD.DatabaseServices namespace (and the other namespaces that namespace is dependent on). Visit www.autodesk.com/realdwg for more information on RealDWG, or step into DE215-4 There's More to .DWG Than AutoCAD.

Further reading
Here are a few places you can go to for more information on the AutoCAD .NET API: x www.autodesk.com/developautocad - for a general overview of the AutoCAD APIs and publicly available resources. This includes the excellent Introduction to AutoCAD .NET Programming DevTV recording by Fenton Webb. www.autodesk.com/apitraining - if youre interested in attending classroom training delivered by the Autodesk Developer Network team. www.autodesk.com/joinadn - to find out how becoming a member of the Autodesk Developer Network can help your application development efforts, including our members-only knowledgebase and unlimited technical support. www.objectarx.com to download the ObjectARX SDK, which includes AutoCAD .NET API documentation and samples.

x x

18

DE205-4: AutoCAD .NET Basics

blogs.autodesk.com/through-the-interface Kean Walmsleys blog focusing primarily on AutoCAD APIs. Kean is senior manager of the global Autodesk Developer Technical Services team (the team who support our ADN partners). discussion.autodesk.com/forum.jspa?forumID=152 the Autodesk public discussion group for the AutoCAD .NET API.

Acknowledgements
Thank you to everyone in the Autodesk Developer Technical Services team (past and present) for their contributions to the training material and SDK samples on which Ive based AutoCAD .NET Basics. And thank you to you for signing up for my class.

19

Potrebbero piacerti anche