AutoCAD Basics - Autodesk Community

Transcription

12/3/2008 - 10:15 am - 11:45 am Room:San Polo 3404 (MSD)AutoCAD .NET BasicsStephen Preston - Americas Manager, Developer Technical Services, AutodeskDE205-4Wondering what all the hype is around .NET? We'll give you the basic information you need toget up to speed on writing your own .NET applications based on the AutoCAD .NET applicationprogramming interface (API). This foundation class includes: an overview of the .NETFramework 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 CADentities to the DWG database; and how to traverse the entities already in the DWG. Make sureyou 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 supportengineer and then as manager of the EMEA (Europe, Middle East, and Africa) Team. In those roles, hisresponsibilities included support for the AutoCAD APIs, including ObjectARX and AutoCAD .NET, as well asAutoCAD OEM and RealDWG technologies. Currently, he manages the Developer Technical Services Teamin the Americas and serves as Workgroup Lead, working closely with the AutoCAD engineering team on futureimprovements in the AutoCAD APIs. Stephen started his career as a scientist, and has a Ph.D in Atomic andLaser Physics from the University of Oxford.Stay Connect with AU all year at www.autodeskuniversity.comr

DE205-4: AutoCAD .NET BasicsAutoCAD .NET Basics What this seminar is (and what it isn’t) AutoCAD .NET Basics is an introduction to the AutoCAD .NET API. The class is intended toform a ‘foundation’ for the other .NET seminars being delivered by the Autodesk DeveloperNetwork team. These are:DE305-3 – AutoCAD .NET: A TourDE315-2 – AutoCAD .NET: Developing a User InterfaceDE401-1 – AutoCAD .NET: Using .NET with your LISP ApplicationsThis is not a beginner’s class on programming. The seminar assumes that you have a basicunderstanding 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 theAutoCAD .NET API1.If you’ve never programmed before, then you’re probably better signing up for a hands on classto get you started. Or sign up for DE305-3 – AutoCAD .NET: A Tour if you want a high-altitudefly-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 ‘ManagedObjectARX’) was released with AutoCAD 2005. Before then, use of the .NET Framework withAutoCAD was restricted to automating AutoCAD from an external .NET application throughCOM Interop. Using COM Interop is really just using .NET as a glorified VB6 application, and isvery different from native .NET programming.The AutoCAD 2005 .NET API was a preview version. It did include the classes required toaccess 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 fewarchitectural changes to allow greater flexibility. The main change was the introduction ofTransactions as the primary means of modifying the DWG Database. (The 2005 API relied onthe Open/Close model favored by ObjectARX2 programmers). The 2006 API release completedthe DWG Database access functionality (adding a few classes for AutoCAD entities that were1A note to beginners – ‘API’ means ‘Application Programming Interface’. That’s the set of functionsAutoCAD exposes for you to use in your application to make AutoCAD do what you want.2The AutoCAD .NET API is a wrapper on top of the (unmanaged) C ObjectARX API. ObjectARXprogrammers have a big advantage over VB or LISP programmers, because the AutoCAD .NET ObjectModel is based on ObjectARX.3

DE205-4: AutoCAD .NET Basicsmissing from the 2005 release), and adding lots of ‘Editor’ functionality (such asInputPointMonitors, SelectionSets, advanced command line interaction, etc.) and acomprehensive 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. Infact, 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 featuresintroduced in Framework 2, it is no longer possible to develop AutoCAD .NET applications usingan IDE that relies on older .NET Frameworks3.A Hello World tutorial As you’re really keen to learn the AutoCAD .NET API, you’ll have picked up this handout whenyou arrived at AU, and you’re now sitting in your hotel room with your laptop, ready to fire upVisual Studio 20054 to get ahead of the game before the seminar. So go on then – double-clickthat squirly icon and get programming. You know you want to!If you’ve ever been subjected to a ‘learn to program’ tutorial before, you’ll know that everybeginner’s tutorial in the world starts with a ‘Hello World’ project. So who are we to break withdecades of tradition? Once Visual Studio has started, you need to create a new project. Go to the File menu andselect New- Project .Unsurprisingly, this displays the New Project dialog.We’re going to create a small VB.NET project. The steps are pretty much the same for C#; it’sjust the C# syntax around the AutoCAD API calls that differs. We’ll show a C# project in theclass.3. For Visual Studio, this means version 2005 or higher is needed.4You don’t have to buy Visual Studio to write your AutoCAD .NET add-ins. There are a number of freedevelopment environments available. For example, you can use Visual Studio Express, but you have totweak it a little to get it to work – see Kean Walmsley’s blog posting for details (http://through-theinterface.typepad.com/through the interface/2006/07/debugging using.html).4

DE205-4: AutoCAD .NET BasicsClick on the Visual Basic project type and select the Class Library Template. Then give theproject a name. You can call it anything you like, but (being a slave to tradition) I’m going to callit ‘HelloWorld’.When you’ve done that, click OK.Now open the Solution Explorer window (the View- Solution Explorer menu item) if it’s notalready open; double click on My Project; and select the References tab.5

DE205-4: AutoCAD .NET BasicsClick the Add button, select the Browse tab; navigate to C:\Program Files\AutoCAD 2009 (orwherever your AutoCAD is installed), and search for *mgd.dll (i.e. type *mgd.dll in the File nametextbox 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 arethe 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.).6

DE205-4: AutoCAD .NET BasicsBack on the My Project screen References tab, double-click on acdbmgd.dll to display itsProperties, and set Copy Local to False. (This is to ensure your .NET add-in loads the copy ofacdbmgd.dll stored in the AutoCAD folder and doesn’t try to make and load a local copy. Youprobably 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.RuntimeImports Autodesk.AutoCAD.ApplicationServicesImports Autodesk.AutoCAD.DatabaseServicesPublic Class Class1 CommandMethod("HelloWorld") Public Sub MyMethod()Application.ShowAlertDialog("Hello World from VB.NET!")End SubEnd ClassThe Imports statements allow you to use classes from the namespaces you import withouthaving to type out the full namespace. You don’t strictly need them, but the code becomes hardto read otherwise. For example,Application.ShowAlertDialog("Hello World from VB.NET!")becomes7

DE205-4: AutoCAD .NET tion.ShowAlertDialog("HelloWorld from VB.NET!")There are several other Autodesk.AutoCAD namespaces, but these are the three you’ll need injust about every AutoCAD add-in you write. (In this example, DatabaseServices is not strictlynecessary). CommandMethod("HelloWorld") is an attribute. This is telling AutoCAD to run thesubroutine MyMethod when the user types HELLOWORLD on the command line. The rest ofthe code should be self-explanatory.That’s all the code we need. But before we can test our first AutoCAD add-in we have to set onemore project setting. Double-click again on My Project in the Solution Explorer; select theDebug tab; set the Start Action to Start external program; and enter the location of the AutoCADexecutable – the default location is C:\Program Files\AutoCAD 2009\acad.exe. This is tellingVisual Studio that you’re going to load your DLL into the AutoCAD process space to debug it5.Now we’re ready to run our add-in. Hit F5 to start debugging, and AutoCAD will launch. TypeNETLOAD on the command line and hit ENTER. In the NETLOAD file select dialog, navigate tothe location of your compiled .NET assembly DLL. This should be in this location, unless youchanged your default project settings:5The AutoCAD .NET API can only be used from inside the AutoCAD process space. You can’t useadmgd.dll and acdbmgd.dll in a standalone executable. (But see the section on RealDWG at the end ofthis document).8

DE205-4: AutoCAD .NET BasicsThe 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! You’ve just created your first custom command using AutoCAD .NET.But let’s not stop just yet. Switch back to Visual Studio and hit Shift F5 to stop the debuggingsession, open up Class1.vb by double-clicking on it in the Solution Explorer, and replace all thecode in that document with this:Imports Autodesk.AutoCAD.RuntimeImports Autodesk.AutoCAD.ApplicationServicesImports Autodesk.AutoCAD.DatabaseServicesPublic Class Class1 CommandMethod("HelloWorld") Public Sub MyMethod()' Some variable definitionsDim activeDoc As DocumentDim BTR As BlockTableRecord' Store a reference to the currently active document (to make thenext two lines of code shorter)activeDoc Application.DocumentManager.MdiActiveDocument' Start a transaction to edit the DWG databaseUsing trans As Transaction activeDoc.TransactionManager.StartTransaction()' Open BlockTableRecord of currently active space ready to addentity.' (This will be ModelSpace if you've not switched to a layout,otherwise PaperSpace).BTR OpenMode.ForWrite)' Create a new MText entity and set its textDim txt As MText New MTexttxt.Contents "Hello World from VB.NET!"' Add the MText to ults()9

DE205-4: AutoCAD .NET Basics' Add the Mtext to the transactiontrans.AddNewlyCreatedDBObject(txt, True)' Commit transaction so changes persist in the DWG Database.trans.Commit()End UsingEnd SubEnd ClassNow hit F5 again; NETLOAD the HelloWorld.dll; and invoke the HELLOWORLD commandagain. ZOOM EXTENTS and you should see this:Give yourself a big hug – you’ve just created your first drawing using VB.NET! The DWG Database format So now we’ve worked through the ubiquitous ‘Hello World’ tutorial. We ended up waving amagic wand to add some MText to ModelSpace. That was our first glimpse of the DWGDatabase structure, which is the most important part of the AutoCAD .NET object model tolearn. You will never understand the ObjectARX or AutoCAD .NET API until you understand theDWG Database structure. It’s as simple as that. So let’s take a look at it now.The DWG Database is not that different to any other database (an MS Access database, forexample). If you’ve ever done any database programming, then you’re halfway there already.10

DE205-4: AutoCAD .NET BasicsLike any database, the DWG Database consists of a number of tables in which are storedrecords. For example, an MS Access database might contain a table of employees (let’s call itthe EmployeeTable), which might contain a record for each Employee (anEmployeeTableRecord). Like this -In the same way, most of the information in a DWG Database is stored in SymbolTables asSymbolTableRecords. 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 ofSymbolTableRecord.The most important aspect of a CAD application is to be able to draw something, so let’sconcentrate on how AutoCAD stores its graphical Entities6 (Lines, Circles, Polylines, etc) youdraw 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 DWGDatabase by BlockTableRecords. This makes sense if you think about it - Block definitions andModelSpace both just store a bunch of graphical Entities. The only difference is that you have awindow to look into the ModelSpace and PaperSpace BlockTableRecords – the drawingdocument. To view other BlockTableRecords, you have to insert a BlockReference intoModelSpace 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 expandedto show some BlockTableRecords and LinetypeTableRecords. Note the names of theBlockTableRecords in the BlockTable shown on the left screenshot – they include Model Spaceand Paper Space. The right-hand screenshot expands the ModelSpace BlockTableRecord toshow the Entities it contains (two Lines, a Circle and a Polyline in this case). Don’t worry aboutthe AcDb prefix on the class names for now.6Entity has a special meaning in AutoCAD. This is the name given to anything in the DWG Database thatis represented graphically. More generally, we use the word Object (or the DBObject class) to describeanything in the database – that includes both Entities and non-graphical objects.7Available as an ObjectARX sample on the ADN website.11

DE205-4: AutoCAD .NET BasicsThere’s a little more to the DWG Database than just Tables. Notice the Named ObjectsDictionary and Extension Dictionary shown in the Inspector tree. These are used for storing datain the DWG, but are outside the scope of this introductory class.Transactions Continuing with our database theme, it shouldn’t come as a surprise that we have a similarmechanism for modifying the DWG Database as for modifying a relational database – we useTransactions.The concept of a transaction is simple. Any changes you make within a transaction are onlycommitted to the database when the transaction is committed. If anything goes wrong whileyou’re modifying the database within a transaction, then you simply abort the transaction andthe database is returned to the state it was in before the transaction started. This is shown in thesimple flow diagram below.12

DE205-4: AutoCAD .NET BasicsUnique Identifiers As for any database, it’s very important to be able to identify each object stored in the DWGdatabase. Without some kind of unique identifier, there would be no way to distinguish (forexample) one red circle from the other red circles in the drawing. When you add an object to theDWG 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. (Althoughcombining the Handle with the drawing pathname would be unique).Handles are saved with the drawing. When you save and reopen a drawing, each object willhave the same handle as it did last time. The only time an object’s handle will change is if youINSERT the object into a new drawing – then the Handles have to change to avoid clashes withthe Handles in the drawing you’re INSERTing into.The .NET DBObject class – the parent class for all objects that can be stored in the DWGdatabase – 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 anAutoCAD session. No matter how many drawings you open in one session, you’ll never see thesame ObjectId.Unlike a Handle, the ObjectId isn’t saved with the drawing, So when you close and reopen adrawing, the objects in it will most likely have different ObjectIds. AutoCAD uses ObjectIds totrack relationships between objects in a drawing. But when AutoCAD saves these relationshipsin the DWG file, it translates them to handles.The DBObject class exposes an ObjectId property. You will mostly be using ObjectIds (ratherthan handles) in your .NET applications.The following table summarizes the similarities differences between Handles and ObjectIds.HandleObjectIdUnique in DWGYesYesUnique in sessionNoYesSaved with DWGYesNoTo find the ObjectId of an object you have the handle for, you can call theDatabase.GetObjectId() function.13

DE205-4: AutoCAD .NET BasicsTo find the Handle of an object you have an ObjectId for, you can open the object using itsObjectId and then call the DBObject.GetHandle() function.Hello World again Now we’ve covered the basics of the DWG Database structure, Transactions, and ObjectIds,let’s walk through the code for the Hello World MText example we used earlier, starting just afterthe variable declarations in the function First we store a reference to the active document. This is just for convenience, so we don’t haveto write Application.DocumentManager.MdiActiveDocument twice.activeDoc e we can access the Database, we have to start a new transaction. We start a transactionfrom 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 theprogram flow has moved beyond the End Using statement. This just helps us to clean up afterourselves. (Otherwise, we’d have to explicitly call the Transactions Dispose function when we’dfinished with it).To add an Entity to the currently active space (ModelSpace or PaperSpace), we ask thetransaction to open the BlockTableRecord for the current space. We access the ObjectID of thecurrent space using the CurrentSpaceId property of the Database, and pass it to theGetObject() method of the Transaction. Like in any database, we have a choice of opening thetable for Write if we’re planning on adding or removing any records, or for Read if we’re onlyinterested in querying the contents. In this case, we’re planning to add some Mtext to theBlockTableRecord, so we open it for Write.BTR OpenMode.ForWrite)There is an alternative to using the CurrentSpaceId property. We’ll mention it here forcompleteness, 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 weneed to access the Database for the currently active AutoCAD DWG document. That’s this lineof codeDB base14

DE205-4: AutoCAD .NET BasicsNext we open the BlockTable. We open it inside the transaction using theTransaction.GetObject() method. (The ObjectId for the BlockTable is returned by theBlockTableId property).BT trans.GetObject(DB.BlockTableId, OpenMode.ForRead)Then we open the ModelSpace BlockTable Record (again using the transaction)MS enMode.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 theModelSpace BlockTableRecord. If we’d wanted the BlockTableRecord defining Block A, we’dhave called BT(“Block A”). And notice that we’re opening the ModelSpace BlockTableRecordfor Write – that’s because we’re planning on adding some MText to ModelSpace.Next we create a new instance of an MText Entity, set it’s contents to the text we want todisplay, and add it to the current space. The commented code is pretty obvious here. TheSetDatabaseDefaults simply sets the textstyle etc. of the text to the default for this drawing.' Create a new MText entity and set its textDim txt As MText New MTexttxt.Contents "Hello World from VB.NET!"' Add the MText to ults()The next part isn’t quite so obvious ' Add the MText to the transactiontrans.AddNewlyCreatedDBObject(txt, True)We’ve created a new MText instance and added it to ModelSpace, so we need to let theTransaction know about that change. That’s how we can make sure the MText is removed fromthe Database if the Transaction is aborted, or permanently added if the Transaction iscommitted. You have to notify the Transaction like this every time you add something new to theDWG Database.Finally, we commit the Transaction. If we get to this line of code, then everything worked fineand there were no errors. Committing the Transaction makes our changes permanent and tidiesup after us (closing everything that we opened).' Commit transaction so changes persist in the DWG Database.trans.Commit()By the way, I’ve not put any error handling in this simple code. Error handling is a very importantpart of .NET, and we will cover that briefly in the seminar.15

DE205-4: AutoCAD .NET BasicsNavigating the AutoCAD .NET Object Model By now, you’ll be starting to grasp what’s needed to add stuff to your drawings. The AutoCAD.NET API exposes a number of namespaces (some of which we touched on briefly alreadywhen we introduced the Imports keyword). These namespaces hold the classes you need towork with AutoCAD. Let’s take a quick look at how you can find out the classes and functionsavailable to you. We’ll focus here on the Autodesk.AutoCAD.DatabaseServices namespace,because (as its name suggests) that’s the namespace that stores the .NET classes used toaccess the DWG Database. What follows assumes knowledge of basic Object-Orientedprogramming concepts8, particularly inheritance.A good way to view the classes available in a namespace is to use the Visual Studio ObjectBrowser (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 thenamespaces it contains.Now expand the DatabaseServices namespace in the Object Browser, scroll down to the MTextclass and expand the tree below it as far as DBObject. Do the same with Line.8See (for example) http://en.wikipedia.org/wiki/Object-oriented programming for an overview of this.16

DE205-4: AutoCAD .NET BasicsExpanding the tree in this way exposes the inheritance hierarchy of that class9. We can see thatMText 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 there’s a further layer of abstraction. A Line is a type of Curve, which isa type of Entity, which is a type of DBObject. Arcs, Circles and Polylines (to name but a few) arealso types of Curve.For our purposes, we can consider the base class for every object that can reside in a DWGDatabase to be DBObject. This means that anything you can access inside the DWG is derivedfrom DBObject. There are other classes further up the hierarchy, but we don’t normally workwith 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, andyou’ll see these listed to the right. Here we’ve scrolled down to show the Contents property weused in the sample code. Clicking on a method or property displays a function signature (asshown in the screenshot). If you now click on Entity in the expanded MText class node, you’llsee all the methods, properties and events that MText inherits from its parent Entity class (andthat 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 seewhat’s there. Here are the inheritance hierarchies for BlockTable and BlockTableRecord. Youcan see that BlockTable is a type of SymbolTable, and BlockTableRecord is a type ofSymbolTableRecord – as discussed earlier. Notice that these are not graphical entities, sothey’re not a type of Entity. Look at the other Autodesk.AutoCAD namespaces as well andnotice the different class hierarchies in those.9Object Browser shows a child to parent inheritance hierarchy. A parent to child diagram is better forstudying which classes share common ‘ancestors’. The ObjectARX SDK includes such a diagram in the ObjectARX SDK \classmap folder.10You could also define an Entity as anything that is owned by (or stored in) a BlockTableRecord.17

DE205-4: AutoCAD .NET BasicsAnd a final note about the class names displayed by Inspector we showed earlier - Thelanguage of AutoCAD is ObjectARX. The .NET API is a thin wrapper on top of this. The classesin the DatabaseServices namespace are the same as those prefixed by AcDb in ObjectARX. Sowhen you see AcDbLine in ObjectARX, this translates toAutodesk.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 filefrom your own standalone application. That means your application can work with the DWGformat even without AutoCAD installed. RealDWG is used internally by all Autodeskapplications, including AutoCAD itself. RealDWG includes a .NET API that is a subset of the fullAutoCAD .NET API. Obviously, an API that works without requiring AutoCAD doesn’t includeany AutoCAD Editor specific functionality (e.g. viewing a drawing, defining commands,responding to mouse movements, creating SelectionSets, etc.), but it does include all of theAutoCAD .NET API needed to directly access the DWG Database from a standaloneapplication. That’s the Autodesk.AutoCAD.DatabaseServices namespace (and the othernamespaces 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:xwww.autodesk.com/developautocad - for a general overview of the AutoCAD APIs andpublicly available resources. This includes the excellent ‘Introduction to AutoCAD .NETProgramming’ DevTV recording by Fenton Webb.xwww.autodesk.com/apitraining - if you’re interested in attending classroom trainingdelivered by the Autodesk Developer Network team.xwww.autodesk.com/joinadn - to find out how becoming a member of the AutodeskDeveloper Network can help your application development efforts, including ourmembers-only knowledgebase and unlimited technical support.xwww.objectarx.com – to download the ObjectARX SDK, which includes AutoCAD .NETAPI documentation and samples.18

DE205-4: AutoCAD .NET Basicsxblogs.autodesk.com/through-the-interface – Kean Walmsley’s blog focusing primarily onAutoCAD APIs. Kean is senior manager of the global Autodesk Developer TechnicalServices team (the team who support our ADN mID 152 – the Autodesk public discussiongroup 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 I’ve based AutoCAD.NET Basics.And thank you to you for signing up for my class.19

DE205-4: AutoCAD .NET Basics 6 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'.