Set 1
Set 1
The database-related subset of ObjectARX, which includes support for custom objects and entities.
These APIs do not include classes that interact with the AutoCAD editor or provide user interface
functionality.
RealDWG
A separately licensed SDK for developing host applications that use ObjectDBX to read and write
DWG and DXF files without AutoCAD. See the autodesk.com Developer Center for more
information about the RealDWG SDK.
Object Enabler
A module with the .dbx extension that defines custom DWG and DXF database objects and entites
using only the ObjectDBX portion of the ObjectARX SDK. An Object Enabler is not dependent on
AutoCAD and can load in any RealDWG host application.
Note Autodesk supports a developer registration scheme to prevent namespace conflicts between
different applications. Each registered developer chooses one or more registered developer symbols
(RDS) to use exclusively. Please select a four-character string and register it at
http://www.autodesk.com/symbreg/index.htm .
As a developer, you can use ObjectARX to accomplish the following tasks:
Access the AutoCAD database
Interact with the AutoCAD editor
Create user interfaces using the MicrosoftFoundation Classes (MFC)
Support the multiple document interface (MDI)
Create custom classes
Build complex applications
Interact with other programming environments
The next sections take a brief look at these topics. They will be discussed in greater detail throughout
the book.
Topics in this section
Accessing the AutoCAD Database
Interacting with the AutoCAD Editor
Creating User Interfaces with MFC
Supporting MDI
Creating Custom Classes
Building Complex Applications
ObjectARX appli
An AutoCAD drawing is a collection of objects stored in a database. These objects represent not only
graphical entities, but also internal constructs such as symbol tables and dictionaries. ObjectARX
provides your application with access to these database structures. In addition, you can create new
Accessing the AutoCAD Database
Page 2 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
database objects for your specific application.
ObjectARX provides classes and member functions to interact with the AutoCAD editor. You can register
commands with AutoCAD that will be treated as built-in commands. Your application can receive and
respond to notification about a variety of events that occur within AutoCAD.
ObjectARX applications can be built with a dynamically linked MFC library that is shared with AutoCAD.
You can use this library to create standard Microsoft Windows graphical user interfaces (GUIs).
With ObjectARX, you can create applications that will support the AutoCAD multiple document interface,
and you can ensure that your applications will interact properly with other applications in the Microsoft
Windows environment.
You can leverage the classes in the ObjectARX hierarchy to create your own custom classes. In addition,
you can make use of the extensive graphics libraries of ObjectARX when creating custom classes.
ObjectARX supports the development of complex applications, providing the following features:
Notification
Transaction management
Deep cloning
Reference editing
Protocol extension
Proxy object support
ObjectARX provides managed wrapper classes that allow you to use the Microsoft .NET Framework and
to write programs in other languages such as VB.NET and C#. ObjectARX applications can communicate
with other programming interfaces, such as Visual LISP, ActiveX Automation, and COM. In addition,
ObjectARX applications can interact with the Internet, by associated URLs with entities, and by loading
and saving drawing files from the Web.
Interacting with the AutoCAD Editor
Creating User Interfaces with MFC
Supporting MDI
Creating Custom Classes
Building Complex Applications
Page 3 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
You can access the ObjectARX online documentation from the docs directory of the ObjectARX SDK.
Open arxdoc.chm to view all of the help files together.
Note
Some subsets of the ObjectARX SDK do not include the directory. You can download the documentation
separately or as part of the complete SDK.
The following online documents are provided with ObjectARX:
What's New in ObjectARX. Lists ObjectARX APIs that have been added for this release.
ObjectARX Developer's Guide. Explains ObjectARX and ObjectDBX
database stores the objects and entities that make up an AutoCAD drawing. This section
discusses the key elements of the database: entities, symbol tables, and the named object dictionary.
This section also introduces object handles, object IDs, and the protocol for opening and closing
database objects. Sample code gives an example of creating entities, layers, and groups, and adding
objects to the database.
Topics in this section
AutoCAD Database Overview
Essential Database Objects
Creating Objects in AutoCAD
Creating Objects in ObjectARX
An AutoCAD drawing is a collection of objects stored in a database. Some of the basic database objects
are entities, symbol tables, and dictionaries. Entities are a special kind of database object that have a
graphical representation within an AutoCAD drawing. Lines, circles, arcs, text, solids, regions, splines,
and ellipses are examples of entities. A user can see an entity on the screen and can manipulate it.
Symbol tables and dictionaries are containers used to store database objects. Both container objects
map a symbol name (a text string) to a database object. An AutoCAD database includes a fixed set of
symbol tables, each of which contains instances of a particular class of symbol table record. You cannot
add a new symbol table to the database. Examples of symbol tables are the layer table
(AcDbLayer Tabl e), which contains layer table records, and the block table (AcDbBl ockTabl e), which
contains block table records. All AutoCAD entities are owned by block table records.
Dictionaries provide a more generic container for storing objects than symbol tables. A dictionary can
contain any object of the type AcDbObj ect or subclass thereof. The AutoCAD database creates a
Database Primer
AutoCAD Database Overview
Page 12 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
dictionary called the named object dictionary when it creates a new drawing. The named object
dictionary can be viewed as the master table of contents for all of the dictionaries associated with the
database. You can create new dictionaries within the named object dictionary and add new database
objects to them.
The following figure shows the key components of the AutoCAD database.
During AutoCAD edit sessions, you can obtain the database for the current drawing by calling the
following global function:
Topics in this section
Multiple Databases
Obtaining Object IDs
Multiple databases can be loaded in a single AutoCAD session. Each object in the session has a handle
and an object ID. A handle uniquely identifies the object within the scope of a particular database,
whereas an object ID uniquely identifies the object across all databases loaded at one time. An object
ID only persists during an edit session, but a handle gets saved with the drawing. In contrast to the
object ID, an object handle is not guaranteed to be unique when multiple databases are loaded in an
AutoCAD session.
With an object ID, you can obtain a pointer to an actual database object so that you can perform
operations on it. For an example, see Opening and Closing ObjectARX Objects.
You can obtain an object ID in a number of ways:
Create an object and append it to the database. The database then gives the object an ID and
returns it to you.
Use the database protocol for obtaining the object ID of the objects that are created automatically
when a database is created (such as the fixed set of symbol tables and the named object
dictionary).
Use class-specific protocol for obtaining object IDs. Certain classes, such as symbol tables and
dictionaries, define objects that own other objects. These classes provide protocol for obtaining the
acdbHost Appl i cat i onSer vi ces( ) - >wor ki ngDat abase( )
Multiple Databases
Obtaining Object IDs
Page 13 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
object IDs of the owned objects.
Use an iterator to step through a list or set of objects. The AcDb library provides a number of
iterators that can be used to step through various kinds of container objects
(AcDbDi ct i onar yI t er at or , AcDbObj ect I t er at or ).
Query a selection set. After the user has selected an object, you can ask the selection set for the list
of entity names of the selected objects, and from the names convert to the object IDs. For more
information on selection sets, see Entities.
As objects are created in AutoCAD, they are added to their appropriate container object in the database.
Entities are added to the records in the block table. Symbol table records are added to the appropriate
symbol tables. All other objects are added to the named object dictionary or to objects that are owned
by other objects (and, ultimately, by the named object dictionary), or to an extension dictionary. The
scenario in the following section, Creating Objects in AutoCAD details this process. Extension
dictionaries are discussed in the section Extension Dictionary.
To be usable, a database must have at least the following set of objects:
A set of nine symbol tables that includes the block table, layer table, and linetype table. The block
table initially contains three records: a record called *MODEL_SPACE, and two paper space records
called *PAPER_SPACE and *PAPER_SPACE0. These block table records represent model space and
the two predefined paper space layouts. The layer table initially contains one record, layer 0. The
linetype table initially contains the CONTINUOUS linetype.
A named object dictionary. When a database is created, this dictionary already contains four
database dictionaries: the GROUP dictionary, MLINE style dictionary, layout dictionary, and plot style
name dictionary. Within the MLINE style dictionary, the STANDARD style is always present.
These objects can be automatically created in a new database by passing kTr ue in for the
AcDbDatabase constructor's bui l dDef aul t Dr awi ng argument. Passing in kFal se creates an empty
database into which a DWG or DXF
code in this section creates the same entities as those in the previous section
(a line and a circle). Code for creating a new layer, changing the color of the line, and adding a group to
the GROUP dictionary is also shown.
Topics in this section
Creating Entities
Creating a New Layer
Opening and Closing ObjectARX Objects
Adding a Group to the Group Dictionary
The following ObjectARX code creates the line and adds it to the model space block table record:
The cr eat eLi ne( ) routine obtains the block table for the current drawing. Then it opens the model
space block table record for writing. After closing the block table, it adds the entity to the block table
record and then closes the block table record and the entity.
Note
When you are done using any ObjectARX objects, you must explicitly close them as soon as possible.
The following cr eat eCi r cl e( ) routine creates the circle and adds it to the model space block table
Creating Objects in ObjectARX
Creating Entities
AcDbObj ect I d
cr eat eLi ne( )
{
AcGePoi nt 3d st ar t Pt ( 4. 0, 2. 0, 0. 0) ;
AcGePoi nt 3d endPt ( 10. 0, 7. 0, 0. 0) ;
AcDbLi ne *pLi ne = new AcDbLi ne( st ar t Pt , endPt ) ;
AcDbBl ockTabl e *pBl ockTabl e;
acdbHost Appl i cat i onSer vi ces( ) - >wor ki ngDat abase( )
- >get Symbol Tabl e( pBl ockTabl e, AcDb: : kFor Read) ;
AcDbBl ockTabl eRecor d *pBl ockTabl eRecor d;
pBl ockTabl e- >get At ( ACDB_MODEL_SPACE, pBl ockTabl eRecor d,
AcDb: : kFor Wr i t e) ;
pBl ockTabl e- >cl ose( ) ;
AcDbObj ect I d l i neI d;
pBl ockTabl eRecor d- >appendAcDbEnt i t y( l i neI d, pLi ne) ;
pBl ockTabl eRecor d- >cl ose( ) ;
pLi ne- >cl ose( ) ;
r et ur n l i neI d;
}
Page 16 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
record:
The following code obtains the layer symbol table from the database, creates a new layer table record,
and names it (ASDK_MYLAYER). The layer table record is then added to the layer table.
All code examples shown in this section illustrate the protocol for opening and closing objects that you'll
need to observe whenever you work with database-resident objects. This protocol ensures that objects
are physically in memory when they need to be accessed but can be paged out to disk when they're not
needed. Before you can modify an object, you need to open it, as shown in the following example:
The open functions have a mode parameter that specifies whether you are opening the object for read,
write, or notify. While the object is open for write, you can modify it. When you are finished, you must
explicitly close the object as shown in the following example, regardless of the mode in which it was
opened:
AcDbObj ect I d
cr eat eCi r cl e( )
{
AcGePoi nt 3d cent er ( 9. 0, 3. 0, 0. 0) ;
AcGeVect or 3d nor mal ( 0. 0, 0. 0, 1. 0) ;
AcDbCi r cl e *pCi r c = new AcDbCi r cl e( cent er , nor mal , 2. 0) ;
AcDbBl ockTabl e *pBl ockTabl e;
acdbHost Appl i cat i onSer vi ces( ) - >wor ki ngDat abase( )
- >get Symbol Tabl e( pBl ockTabl e, AcDb: : kFor Read) ;
AcDbBl ockTabl eRecor d *pBl ockTabl eRecor d;
pBl ockTabl e- >get At ( ACDB_MODEL_SPACE, pBl ockTabl eRecor d,
AcDb: : kFor Wr i t e) ;
pBl ockTabl e- >cl ose( ) ;
AcDbObj ect I d ci r cl eI d;
pBl ockTabl eRecor d- >appendAcDbEnt i t y( ci r cl eI d, pCi r c) ;
pBl ockTabl eRecor d- >cl ose( ) ;
pCi r c- >cl ose( ) ;
r et ur n ci r cl eI d;
}
Creating a New Layer
voi d
cr eat eNewLayer ( )
{
AcDbLayer Tabl e *pLayer Tabl e;
acdbHost Appl i cat i onSer vi ces( ) - >wor ki ngDat abase( )
- >get Symbol Tabl e( pLayer Tabl e, AcDb: : kFor Wr i t e) ;
AcDbLayer Tabl eRecor d *pLayer Tabl eRecor d =
new AcDbLayer Tabl eRecor d;
pLayer Tabl eRecor d- >set Name( " ASDK_MYLAYER" ) ;
/ / Def aul t s ar e used f or ot her pr oper t i es of
/ / t he l ayer i f t hey ar e not ot her wi se speci f i ed.
/ /
pLayer Tabl e- >add( pLayer Tabl eRecor d) ;
pLayer Tabl e- >cl ose( ) ;
pLayer Tabl eRecor d- >cl ose( ) ;
}
Opening and Closing ObjectARX Objects
acdbOpenObj ect ( pObj ect , obj I d, AcDb: : kFor Wr i t e) ;
Page 17 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
The following is sample code for changing the color of an entity:
New instances of an object are considered to be open for write. Some functions, such as the
AcDbBl ockTabl e: : get At ( ) function, obtain an object ID and open the object at the same time. An
object can't be closed until it has been added to the database. You own the object and can freely delete
it at any time before the object is added to the database.
However, once the object has been added to the database, you cannot delete it directly. You can call the
AcDbObj ect : : er ase( ) function, which marks the object as erased. Erased objects remain in the
database until the database is destroyed, but do not get saved when the drawing is saved.
Warning
Directly deleting an object that has been added to the database will cause AutoCAD to terminate.
The following code creates a group (pGr oup) out of the line and circle created in the cr eat eLi ne( ) and
cr eat eCi r cl e( ) functions and puts the group into the GROUP dictionary. The object IDs of the line and
circle are passed into the function. Notice how the GROUP dictionary is opened for writing, modified, and
then explicitly closed.
pObj ect - >cl ose( ) ;
Acad: : Er r or St at us
changeCol or ( AcDbObj ect I d ent I d, Adesk: : UI nt 16 newCol or )
{
AcDbEnt i t y *pEnt i t y;
acdbOpenObj ect ( pEnt i t y, ent I d,
AcDb: : kFor Wr i t e) ;
pEnt i t y- >set Col or I ndex( newCol or ) ;
pEnt i t y- >cl ose( ) ;
r et ur n Acad: : eOk;
}
Adding a Group to the Group Dictionary
voi d
cr eat eGr oup( AcDbObj ect I dAr r ay& obj I ds, char * pGr oupName)
{
AcDbGr oup *pGr oup = new AcDbGr oup( pGr oupName) ;
/ / Put t he gr oup i n t he gr oup di ct i onar y whi ch r esi des
/ / i n t he named obj ect di ct i onar y.
/ /
AcDbDi ct i onar y *pGr oupDi ct ;
acdbHost Appl i cat i onSer vi ces( ) - >wor ki ngDat abase( )
- >get Gr oupDi ct i onar y( pGr oupDi ct , AcDb: : kFor Wr i t e) ;
AcDbObj ect I d pGr oupI d;
pGr oupDi ct - >set At ( pGr oupName, pGr oup, pGr oupI d) ;
pGr oupDi ct - >cl ose( ) ;
/ / Now t hat t he gr oup has been added, i t has an Obj ect I D.
/ / Thi s i s i mpor t ant si nce t he gr oup wi l l become a per si st ent
/ / r eact or f or t he added ent i t i es. . .
f or ( i nt i = 0; i < obj I ds. l engt h( ) ; i ++) {
pGr oup- >append( obj I ds[ i ] ) ;
}
pGr oup- >cl ose( ) ;
}
ObjectARX Application Basics
Page 18 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
This section describes how to write and run an ObjectARX
to the ObjectARX application and shows how the application typically responds to those
messages. This section also discusses the registration of new commands, how to load and unload an
application, AutoCAD's demand loading feature, and error handling.
Topics in this section
Creating an ObjectARX Application
Example Application
Registering New Commands
Loading an ObjectARX Application
Unloading an ObjectARX Application
Application Automatic Loading
Demand Loading
ARX Command
Running ObjectARX Applications from AutoLISP
Error Handling
Polymorphic Type Conversions
An ObjectARX application is a DLL that shares AutoCAD 's address space and makes direct function calls
to AutoCAD. ObjectARX applications typically implement commands that can be accessed from within
AutoCAD. These commands are often implemented using custom classes. Creating an ObjectARX
application involves the following general steps.
To create an ObjectARX application
1. Create custom classes to implement new commands.
You can derive custom classes from most of the ObjectARX hierarchy and symbol table classes.
2. Determine which AutoCAD messages your ObjectARX application will handle.
AutoCAD sends a variety of messages to ObjectARX applications, indicating that particular events
have occurred within AutoCAD. You decide which messages your application will respond to, and
which actions will be triggered.
3. Implement an entry point for AutoCAD.
AutoCAD calls into an ObjectARX application through the acr xEnt r yPoi nt ( ) function, which replaces
the mai n( ) function of a C++ program. You are responsible for implementing the acr xEnt r yPoi nt ( )
function in your application. The acr xEnt r yPoi nt ( ) function calls the functions that you've
associated with specific AutoCAD messages.
4. Implement initialization.
Within your ObjectARX application, you will need to initialize any custom classes that you have
created, and rebuild the ObjectARX runtime class tree. Additionally, if you are adding commands,
you must register them with AutoCAD.
5. Prepare for unloading.
To create a well-behaved ObjectARX application, you must remove any custom classes and
commands when your application is unloaded.
The following sections discuss the general steps of developing an ObjectARX application in more detail.
Topics in this section
Creating an ObjectARX Application
Page 19 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Creating Custom Classes
Responding to AutoCAD Messages
Implementing an Entry Point for AutoCAD
Initializing an ObjectARX Application
Preparing for Unloading
You can derive custom classes from most of the ObjectARX class hierarchy. This allows you to leverage
the functionality of the ObjectARX classes when creating your own objects. Defining custom classes is
discussed in detail in Deriving a Custom ObjectARX Class
There are four categories of messages that AutoCAD sends to ObjectARX applications:
Messages that are sent to all applications
Messages that are sent only if the application has registered an AutoLISP
\ \ HKEY_LOCAL_MACHI NE\ SOFTWARE\ Aut odesk\ Obj ect DBX\ <VERSI ON>\ Appl i cat i ons\ <Appl i cat i on
DESCRI PTI ON: REG_SZ: Pol yCad
LOADCTRLS: REG_DWORD: 0xd
LOADER: REG_SZ: C: \ Pr ogr amFi l es\ pol ysampi nc\ pol yui . dbx
Demand Loading on Command
Page 35 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
In this example, the developer's registered developer prefix (ASDK) is used as the prefix for all
commands to ensure that there will be no possible conflict with commands of the same name in other
applications.
Note Invoking the command using Group prefix will also disambiguate the command. In other words,
GROUP_NAME.COMMAND_NAME will demand load the command associated with the specified command
group.
The ObjectARX application must also include the appropriate calls to the acedRegCmds macro for
demand loading on command to work.
Demand loading of an ObjectARX application on AutoCAD startup can be specified by using 0x02 (or you
can perform an OR 0x02 with another legitimate value) with the LOADCTRLS value in the system registry,
as shown here.
If your application defines custom object context menus, you can provide registry settings to guarantee
that the required modules are loaded when the user right-clicks on one of your objects. To do so, add a
key to the Cont ext Handl er s registry section. On a power user's machine, the Cont ext Handl er s hive
appears at the following registry location:
The name of the key should be your custom object class name. The value of the key should be a
comma-delimited list of logical names of the applications that need to be loaded. These logical names
must match Appl i cat i onName keys that exist in the Appl i cat i ons registry hive, as described in
Creating AutoCAD Subkeys and Values.
The following sample illustrates a Cont ext Handl er key for AcDbTabl e objects:
\ \ HKEY_LOCAL_MACHI NE\ SOFTWARE\ Aut odesk\ Aut oCAD\ R20. 0\
ACAD- E001: 409\
Appl i cat i ons\ pol ysamp\
DESCRI PTI ON: REG_SZ: Pol yCad
LOADCTRLS: REG_DWORD: 0xd
LOADER: REG_SZ: C: \ Pr ogr amFi l es\ pol ysampi nc\ pol yui . ar x
Commands\
ASDKPOLY: REG_SZ: ASDKPOLY
ASDKDRAGPOLY: REG_SZ: ASDKDRAGPOLY
ASDKPOLYEDI T: REG_SZ: ASDKPOLYEDI T
Gr oups\
ASDK: REG_SZ: ASDK
. . .
Demand Loading on AutoCAD Startup
\ \ HKEY_LOCAL_MACHI NE\ SOFTWARE\ Aut odesk\ Aut oCAD\ R20. 0\
ACAD- E001: 409\
Appl i cat i ons\ Pol yCAD\
LOADCTRLS: REG_DWORD: 0x02
Demand Loading on Context Menu Invocation
\ \ HKEY_LOCAL_MACHI NE\ SOFTWARE\ Aut odesk\ Aut oCAD\ R20. 0\
ACAD- E001: 409\
Cont ext Handl er s
Page 36 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
When a user right-clicks on an AcDbTabl e object, this key guarantees that the modules associated with
logical names AcadTabl e and AcSmSheet Li st are loaded.
Topics in this section
Loading .NET Applications on AutoCAD Startup
Loading .NET Modules on Command Invocation
Under the root key HKEY_CURRENT_USER\ Sof t war e\ Aut odesk\ Aut oCAD\ R20. 0\ ACAD- E001: 409
\ Appl i cat i ons, create a key for your application. Then create a number of values:
DESCRIPTION
A string value describing the purpose of the module
LOADCTRLS
A DWORD value that must be set to 2 for loading the module on startup
MANAGED
A DWORD that should be set to "1" for .NET modules
LOADER
A string value describing the purpose of the module
To support .NET demand loading, a couple more keys need to be added to the application registry value.
To begin, LOADCTRLS needs to be changed to a value of 12.
Beneath a Commands key, create as many string values ascommands, each with the name of the
"global" command name, and the value of the "local" command name.
Beneath a Groups key, do the same for the command-groups we've registered our commands under.
ObjectARX provides APIs that simplify the task of writing demand load entries to the registry. Though
install time is preferable for writing initial registry entries, these APIs may be useful if you need to
change your demand load information at runtime. For instance, an application could write default
settings to HKEY_LOCAL_MACHI NE at installation, and then use these APIs to write user-specific values to
\ \ HKEY_LOCAL_MACHI NE\ SOFTWARE\ Aut odesk\ Aut oCAD\ R20. 0\
ACAD- E001: 409\
Cont ext Handl er s\
AcDbTabl e: REG_SZ: AcadTabl e, AcSmSheet Li st
Loading .NET Applications on AutoCAD Startup
Loading .NET Modules on Command Invocation
Using ObjectARX APIs to Simplify Registry Setup
Page 37 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
HKEY_CURRENT_USER at runtime.
The AcadAppI nf o class functions and the acr xRegi st er App( ) global function write registry entries to
the location dictated by the current user's privileges. If the user has power user privileges, then the
entries are written under HKEY_LOCAL_MACHI NE. Otherwise, they are written under HKEY_CURRENT_USER.
The AcadAppI nf o: : wr i t eToRegi st r y( ) function writes all registry entries required for demand loading.
It provides an argument that forces entries to be written to the HKEY_CURRENT_USER hive, even if the
user has write permissions in HKEY_LOCAL_MACHI NE. See writeToRegistry in the ObjectARX Reference for
details.
The following methods provide the ability to write group and command demand load information to the
registry:
writeGroupNameToRegistry
writeCommandNameToRegistry
The acr xRegi st er App( ) global function is a single-call wrapper for AcadAppI nf o that performs partial
registry setup. You can use this function in conjunction with your own AcadAppI nf o object. See
acrxRegisterApp in the ObjectARX Reference for detailed documentation and important caveats.
Topics in this section
Removing System Registry Information
It may be useful to remove ObjectARX application information from the system registry if an application
is upgraded or removed. The ObjectARX API includes the function acr xUnr egi st er App( ) , which is the
counterpart of acr xRegi st er App( ) . It removes information about an application from the AutoCAD
section of the system registry.
The following sample (from the ObjectARX SDK polysamp sample program) illustrates writing demand
loading keys for an ObjectARX application that registers groups and commands:
Removing System Registry Information
Code Sample: Writing Demand Loading Keys
Page 38 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Note Object Enablers use an abbreviated version of the ObjectARX registry format. See the Registering
Object Enablers for Demand Loadingsection in the Object Enablers chapter for more details.
Once system registry information has been created for demand loading, that same information can be
used by a set of ObjectARX functions to load, unload, and monitor the presence of ObjectARX
applications independent of the demand-loading feature. The AppName argument used by the first two of
these functions is the logical application name.
The following ObjectARX functions can be used with registered application names:
bool acr xLoadApp ( " AppName" )
This function takes a single argument, which represents the case-insensitive logical name of the
application to be loaded. The function returns 0 if the load failed, or 1 if the load succeeds.
bool acr xUnl oadApp ( " AppName" )
This function takes a single argument, which represents the case-insensitive logical name of the
application that was previously loaded. The function returns 0 if the unload fails, or 1 if it succeeds.
voi d *acr xLoadedApps ( )
This function returns an array of strings as a voi d *, containing the logical application name of each
application that is currently loaded. The function returns NULL if no applications are loaded. It is the
caller's responsibility to release the space allocated for the returned strings.
The following sections describe the ARX command and its options. The initial prompt is as follows:
?/Load/Unload/Commands/Options: Enter an option or press ENTER
voi d updat eRegi st r y( )
{
/ / Fi l l t he AppI nf o st r uct ur e wi t h our demand l oadi ng det ai l s.
AcadAppI nf o appI nf o;
appI nf o. set AppName( " AsdkPol yCAD" ) ; / / Appl i cat i on name
appI nf o. set Modul eName( acedGet AppName( ) ) ; / / Modul e pat h
appI nf o. set AppDesc( " AsdkPol yCAD" ) ; / / Descr i pt i on
appI nf o. set LoadReason( / / Speci f y when we want t hese t o l oad
AcadApp: : LoadReasons(
AcadApp: : kOnCommandI nvocat i on |
AcadApp: : kOnLoadRequest ) ) ;
/ / Wr i t e t he appI nf o t o t he r egi st r y.
appI nf o. wr i t eToRegi st r y( ) ;
/ / Wr i t e t he gr oup name.
appI nf o. wr i t eGr oupNameToRegi st r y( " ASDK_POLYGON" ) ;
/ / Wr i t e out al l our commands ( Gl obal , Local ) .
appI nf o. wr i t eCommandNameToRegi st r y( " ASDK_POLY" , " POLY") ;
appI nf o. wr i t eCommandNameToRegi st r y( " ASDK_DRAGPOLY" , " DRAGPOLY" ) ;
appI nf o. wr i t eCommandNameToRegi st r y( " ASDK_POLYEDI T" , " POLYEDI T" ) ;
appI nf o. wr i t eCommandNameToRegi st r y( " ASDK_TRANSACT" , " TRANSACT" ) ;
appI nf o. wr i t eCommandNameToRegi st r y( " ASDK_HI LI TPOLY" , "HI LI TPOLY" ) ;
appI nf o. wr i t eCommandNameToRegi st r y( " ASDK_HI LI TSOLI D" , " HI LI TSOLI D" ) ;
appI nf o. wr i t eCommandNameToRegi st r y( " ASDK_CREATEI NSERT" , " CREATEI NSERT" ) ;
appI nf o. wr i t eCommandNameToRegi st r y( " ASDK_HI LI TI NSERT", " HI LI TI NSERT" ) ;
}
Managing Applications with the System Registry
ARX Command
Page 39 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Topics in this section
? -- List Applications
Load
Unload
Commands
Options
Lists the currently loaded ARX applications.
Loads the .arx file that you specify in the standard file dialog box. If FILEDIA is set to 0, a dialog box is
not displayed, and you enter the name of the file to load in response to the following prompt:
Runtime extension file: Enter a name
Unloads the specified ARX program. Some applications cannot be unloaded. See Unloading an
ObjectARX Applicationfor a description of how the programmer decides whether a program can be
unloaded by the user with this command.
Displays all command names in all command groups registered from ARX programs.
Presents developer-related ARX application options.
Options (Group/CLasses/Services): Enter an option
Group
Moves the specified group of commands registered from ARX applications to be the first group
searched when resolving the names of AutoCAD commands. Other registered groups, if there are
any, are subsequently searched, in the same order as before the ARX command was executed.
Command Group Name: Enter the command group name
The search order is important only when a command name is listed in multiple groups. This
mechanism allows different ARX applications to define the same command names in their own
separate command groups. ARX applications that define command groups should publish the group
name in their documentation.
? -- List Applications
Load
Unload
Commands
Options
Page 40 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Group is not intended to be selected by the user directly. The user specifies which group is searched
first by interacting with a script that executes the ARX command with the Group option. This
capability is usually embedded in key menu item scripts. The user selects a menu item from the
script. The key menu item script executes the Group option to establish which group is searched
first, giving commands of the same name (but probably different functionality) from one application
precedence over commands from another.
For example, applications called ABC Construction and XYZ Interiors define command groups ABC
and XYZ, respectively. Most of ABC Construction's commands are named with construction
terminology, while most of XYZ Interiors' commands are named with interior decorating terminology,
but both applications define commands named INVENTORY and ORDERS. When working on the
construction aspects of a drawing, the user chooses a menu item defined by ABC Construction, and
the following script runs:
The script pops the ABC Construction command set to give it top priority and to resolve INVENTORY to
the ABC Construction version of the command. Later, when an interior designer is working on the
drawing with the same set of applications loaded, selecting a key icon ensures that the XYZ Interiors
commands have precedence.
Note Command groups are not related to commands defined in AutoLISP
Note or defined by a call to acedDef un( ) by ObjectARX applications. The software mechanism that
defines command groups is described in Lookup Order.
Classes
Displays a class hierarchy of C++ classes derived from objects registered in the system, whether
registered by AutoCAD or by an ARX program.
Services
Lists the names of all services registered by AutoCAD and by loaded ARX programs.
An ObjectARX application can define a set of functions known to AutoLISP as external functions, by
using acedDef un( ) . After the application is loaded, you can invoke an external function exactly as you
can invoke a built-in or user-defined AutoLISP function. AutoLISP variables can be passed as arguments
to the external function, and the external function can return a result. The external function can also
prompt the user to enter data, either from the keyboard or by specifying points or objects with the
pointing device, and the external function can set Windows help.
The external function can be invoked by an AutoLISP function, as well as interactively. ObjectARX
applications cannot call AutoLISP functions. An ObjectARX application can retrieve and set the value of
AutoLISP symbols (the symbol's data type must be recognizable to a C++ program).
An ObjectARX application can define a new AutoCAD command with the same C: XXX convention as
AutoLISP. You invoke the external function by entering its name at the Command prompt, with no
parentheses.
Defining an external function replaces any previous definition of the same name. If two ObjectARX
applications define functions with the same name, the function in the first application to be loaded is
lost; if you unload the second application, you cannot call the duplicate function.
ARX
Gr oup
ABC
Running ObjectARX Applications from AutoLISP
Error Handling
Page 41 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
The examples in this guide have omitted necessary error checking to simplify the code. However, you'll
always want to check return status and take appropriate action. The following example shows
appropriate use of error checking for several examples shown first in Database Primer
Page 42 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Acad: : Er r or St at us
cr eat eCi r cl e( AcDbObj ect I d& ci r cl eI d)
{
ci r cl eI d = AcDbObj ect I d: : kNul l ;
AcGePoi nt 3d cent er ( 9. 0, 3. 0, 0. 0) ;
AcGeVect or 3d nor mal ( 0. 0, 0. 0, 1. 0) ;
AcDbCi r cl e *pCi r c = new AcDbCi r cl e( cent er , nor mal , 2. 0) ;
i f ( pCi r c == NULL)
r et ur n Acad: : eOut Of Memor y;
AcDbBl ockTabl e *pBl ockTabl e;
Acad: : Er r or St at us es =
acdbHost Appl i cat i onSer vi ces( ) - >wor ki ngDat abase( ) - >
get Symbol Tabl e( pBl ockTabl e, AcDb: : kFor Read) ;
i f ( es ! = Acad: : eOk) {
del et e pCi r c;
r et ur n es;
}
AcDbBl ockTabl eRecor d *pBl ockTabl eRecor d;
es = pBl ockTabl e- >get At ( ACDB_MODEL_SPACE,
pBl ockTabl eRecor d, AcDb: : kFor Wr i t e) ;
i f ( es ! = Acad: : eOk) {
Acad: : Er r or St at us es2 = pBl ockTabl e- >cl ose( ) ;
i f ( es2 ! = Acad: : eOk) {
acr x_abor t ( " \ nApp X f ai l ed t o cl ose Bl ock"
" Tabl e. Er r or : %d" ,
acadEr r or St at usText ( es2) ) ;
}
del et e pCi r c;
r et ur n es;
}
es = pBl ockTabl e- >cl ose( ) ;
i f ( es ! = Acad: : eOk) {
acr x_abor t ( " \ nApp X f ai l ed t o cl ose Bl ock Tabl e. "
" Er r or : %d" , acadEr r or St at usText ( es) ) ;
}
es = pBl ockTabl eRecor d- >appendAcDbEnt i t y( ci r cl eI d,
pCi r c) ;
i f ( es ! = Acad: : eOk) {
Acad: : Er r or St at us es2 = pBl ockTabl eRecor d- >cl ose( ) ;
i f ( es2 ! = Acad: : eOk) {
acr x_abor t ( " \ nApp X f ai l ed t o cl ose"
" Model Space Bl ock Recor d. Er r or : %s" ,
acadEr r or St at usText ( es2) ) ;
}
del et e pCi r c;
r et ur n es;
}
es = pBl ockTabl eRecor d- >cl ose( ) ;
i f ( es ! = Acad: : eOk) {
acr x_abor t ( " \ nApp X f ai l ed t o cl ose"
" Model Space Bl ock Recor d. Er r or : %d" ,
acadEr r or St at usText ( es) ) ;
}
es = pCi r c- >cl ose( ) ;
i f ( es ! = Acad: : eOk) {
acr x_abor t ( " \ nApp X f ai l ed t o"
" cl ose ci r cl e ent i t y. Er r or : %d" ,
acadEr r or St at usText ( es) ) ;
}
r et ur n es;
}
Acad: : Er r or St at us
cr eat eNewLayer ( )
{
AcDbLayer Tabl eRecor d *pLayer Tabl eRecor d
= new AcDbLayer Tabl eRecor d;
i f ( pLayer Tabl eRecor d == NULL)
r et ur n Acad: : eOut Of Memor y;
Acad: : Er r or St at us es
= pLayer Tabl eRecor d- >set Name( " ASDK_MYLAYER" ) ;
i f ( es ! = Acad: : eOk) {
del et e pLayer Tabl eRecor d;
Page 43 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
ObjectARX may be compiled on 32- and 64-bit systems. As such, various ObjectARX specific types are
converted to appropriate values for these systems. Below is a table indicating the type in ObjectARX,
and what it evaluates to for 32- and 64-bit systems:
For reference, the table below specific Microsoft specific types, and how they evaluate in 32- and 64-bit
systems:
This section describes basic database protocol including how to create a database, how to read in a
drawing file, and how to save the database. The wbl ock and i nser t operations are also described here.
For more detailed information on the deepCl one and wbl ock operations, see Deep Cloning
Topics in this section
Initial Database
Creating and Populating a Database
Saving a Database
The wblock Operation
Polymorphic Type Conversions
Typer Name Type in 32-bit Compilation Type in 64-Bit Compilation
Adesk::IntPtr int __int64
Adesk::UIntPtr unsigned int unsigned__int64
Adesk::LongPtr long __int64
AdeskULongPtr unsigned long unsigned__int64
Adesk::IntDbId long __int64
Adesk::GsMarker int __int64
Typer Name 32-bit Compilation 64-Bit Compilation
DWORD_PTR unsigned long unsigned__int64
HALF_PTR short int
INT_PTR int __int64
LONG_PTR long __int64
SIZE_T unsigned long unsigned__int64
SSIZE_T long __int64
UHALF_PTR unsigned short unsigned int
UNIT_PTR unsigned int unsigned__in64
ULONG_PTR unsigned long unsigned__int64
Database Operations
Page 44 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Inserting a Database
Setting Current Database Values
Example of Database Operations
Long Transactions
External References
Indexes and Filters
Drawing Summary Information
Last Saved by Autodesk Software
When an AutoCAD
provides the ability to specify the default file format for the SAVEAS, SAVE, and QSAVE
commands. (The AUTOSAVE command always saves drawings in the native format of the AutoCAD
version being used.)
The class AcApDocument contains an enumeration that defines the format used when saving a drawing
to a file. See SaveFormat enum in the ObjectARX Reference for a list of possible values.
The formatForSave function returns the current save format being used by the SAVEAS, SAVE, and
QSAVE commands:
The value returned may be either the session-wide default setting, or a different setting that the user
has selected for this document. If it is an override for this document, it will not persist across sessions.
The setDefaultFormatForSave function uses one of the SaveFor mat values to set the file format to use
when saving a drawing with the SAVEAS, SAVE, and QSAVE commands. This sets the session-wide
default, which the user may choose to temporarily override for an individual document.
These functions only directly report on or set the file format for interactive commands entered by the
user. If you want your application to use the current save format, every time you wish to save the
database, you will first need to call f or mat For Save( ) , and then use the returned SaveFor mat value to
determine which function to call. For example, if f or mat For Save( ) returned k2000_dxf , you would call
acdbDxf Out As2000( ) to write the database as an AutoCAD 2000 DXF file.
Be sure to take the following into account:
Either you or your user may set a persistent session-wide default format for save that will be
honored by all save commands except AUTOSAVE.
Only the user can temporarily (not persistently between sessions) override this setting for a
particular document.
The f or mat For Save( ) method returns the format in which the user wishes an individual document
to be saved; this will be either the session-wide default or the temporary override, as appropriate.
The AcDbDat abase class contains an overloaded wblock function with four forms that correspond to the
options of the AutoCAD WBLOCK command. These functions can be used to create a new database from
an existing database or to create a new database containing specified entites from an input database.
Saving a Database
Setting the Default File Format
The wblock Operation
Page 46 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Topics in this section
Creating a New Database from an Existing Database
Creating a New Database with Entities
The following function is the equivalent of the WBLOCK* command:
This function creates a new database from the invoked database (t hi s). Any unreferenced symbols in
the input database are omitted in the new database (which makes the new database potentially cleaner
and smaller than the original). However, it does not take care of copying application-defined objects
whose ownership is rooted in the named object dictionary. You need to transfer application data from
the source database to the target database using the AcEdi t or React or notification functions.
The other three forms of the AcDbDat abase: : wbl ock( ) function create a new database whose model
space block table record contains the specified entities from the input database. The first form of this
function copies the entities from a named block table record. The second and third forms of the function
both copy an array of entities, but one includes a parameter specifying how to handle duplicate symbols
or dictionary entries in the new database.
Copying a Named Block
The following function is equivalent to invoking the WBLOCK command with the name of a block
definition:
The bl ockI d argument represents a block table record in the input database. The entities in this block
table record are copied into the new database's model-space block table record. The insert base of the
new database is the block table record's origin.
Copying an Array of Entities
The following function is equivalent to invoking the WBLOCK command and then using the option to
select specific objects and specify an insertion base point:
This function creates a new database that includes the entities specified in the out Obj I ds argument.
Creating a New Database from an Existing Database
Acad: : Er r or St at us
AcDbDat abase: : wbl ock(
AcDbDat abase*& pOut put Db) ;
Creating a New Database with Entities
Acad: : Er r or St at us
AcDbDat abase: : wbl ock(
AcDbDat abase*& pOut put Db,
AcDbObj ect I d bl ockI d) ;
Acad: : Er r or St at us
AcDbDat abase: : wbl ock(
AcDbDat abase*& pOut put Db,
const AcDbObj ect I dAr r ay& out Obj I ds,
const AcGePoi nt 3d* basePoi nt ) ;
Page 47 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
The entities, which can be in the model space or paper space block table records of the input database,
are placed in the model space of the new database. Also included in the new database are the objects
owned by or referred to by those entities, as well as the owners of those objects. The specified point is
the origin point, in world coordinates, for the new drawing (that is, it is the insert base point in the
model space of the new database).
The final version of the AcDbDat abase: : wbl ock( ) function also copies an array of entities and specifies
an insertion base point, but it has an additional parameter specifying how to handle duplicate symbols
or dictionary entries in the new database:
For more information about the dr c parameter, see the wblock documentation in the ObjectARX
Reference.
The insert functions copy one database into the database that the member function is invoked on.
AutoCAD merges the objects that it defines, such as the MLINE style and GROUP dictionaries; however,
it does not take care of copying application-defined objects whose ownership is rooted in the named
object dictionary. You need to transfer application data from the source database to the target database
using the AcEdi t or React or notification functions.
Note The i nser t ( ) functions perform deep cloning, as described in Deep Cloning
If conflicts arise when the source and target databases are being merged (for example, if both
databases have the same linetype name), AutoCAD uses the version in the target database.
The following function is equivalent to a standard drawing INSERT command:
This function copies the entities from the model space of the input database (pDb) into the specified
block table record (pBl ockName) and returns the block ID of the new block table record (bl ockI d). The
application must then create the reference to the block table record and add it to the database.
The following function is equivalent to an AutoCAD INSERT* command:
This function copies the entities from the model space of the input database (pDb) and puts them into
the current space of the new database (paper space or model space), applying the specified
transformation (xf or m) to the entities.
The following version of the i nser t ( ) function copies entities from a named block table record in the
source database to a named block table record in the destination database, creating a new destination
block table record if necessary or replacing the contents of an existing destination block table record:
Acad: : Er r or St at us
AcDbDat abase: : wbl ock(
AcDbDat abase*& pOut put Db,
const AcDbObj ect I dAr r ay& out Obj I ds,
const AcGePoi nt 3d* basePoi nt ,
AcDb: : Dupl i cat eRecor dCl oni ng dr c) ;
Inserting a Database
Acad: : Er r or St at us
AcDbDat abase: : i nser t (
AcDbObj ect I d& bl ockI d,
const char * pBl ockName,
AcDbDat abase* pDb,
bool pr eser veSour ceDat abase = t r ue) ;
Acad: : Er r or St at us
AcDbDat abase: : i nser t (
const AcGeMat r i x3d& xf or m,
AcDbDat abase* pDb,
bool pr eser veSour ceDat abase = t r ue) ;
Page 48 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
If a data property such as color or linetype is not specified for an entity, the database's current value for
that data is used. The following sections outline the functions used to specify the current data values
associated with the database.
Topics in this section
Database Color Value
Database Linetype Value
Database Linetype Scale Value
Database Layer Value
If a color is not specified for an entity, the database's current color value, stored in the CECOLOR
system variable, is used. The following functions set and retrieve the current color value in the
database:
The following functions set and retrieve the current linetype value in the database:
Acad: : Er r or St at us
AcDbDat abase: : i nser t (
AcDbObj ect I d& bl ockI d,
const char * pSour ceBl ockName,
const char * pDest i nat i onBl ockName,
AcDbDat abase* pDb,
bool pr eser veSour ceDat abase = t r ue) ;
Setting Current Database Values
Database Color Value
Acad: : Er r or St at us
AcDbDat abase: : set Cecol or (
const AcCmCol or & col or ) ;
AcCmCol or AcDbDat abase: : cecol or ( ) const ;
Database Linetype Value
Acad: : Er r or St at us
AcDbDat abase: : set Cel t ype(
AcDbObj ect I d obj I d) ;
AcDbObj ect I d AcDbDat abase: : cel t ype( ) const ;
Database Linetype Scale Value
Page 49 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
The database has three linetype scale settings:
A linetype scale setting for the current entity, stored in the CELTSCALE system variable.
A linetype scale setting for the current drawing, stored in the LTSCALE system variable.
A flag that indicates whether to apply linetype scaling to the space the entity resides in or to the
entity's appearance in paper space. This setting is stored in the PSLTSCALE system variable.
The global LTSCALE and PSLTSCALE settings are used when a drawing is regenerated (see Entities). Use
the following functions to set and inquire these values:
The following functions set and retrieve the current layer value in the database:
The following example shows the cr eat eDwg( ) routine, which creates a new database, obtains the
model space block table record, and creates two circles that are added to model space. It uses the
AcDbDat abase: : saveAs( ) function to save the drawing. The second routine, r eadDwg( ) , reads in the
saved drawing, opens the model space block table record, and iterates through it, printing the class
names of the entities it contains.
Acad: : Er r or St at us
AcDbDat abase: : set Lt scal e( doubl e scal e) ;
doubl e AcDbDat abase: : l t Scal e( ) const ;
Acad: : Er r or St at us
AcDbDat abase: : set Cel t scal e( doubl e scal e) ;
doubl e AcDbDat abase: : cel t scal e( ) const ;
Acad: : Er r or St at us
AcDbDat abase: : set Psl t scal e( bool scal e)
bool AcDbDat abase: : psl t scal e( ) const ;
Database Layer Value
Acad: : Er r or St at us
AcDbDat abase: : set Cl ayer (
AcDbObj ect I d obj I d) ;
AcDbObj ect I d AcDbDat abase: : cl ayer ( ) const ;
Example of Database Operations
Page 50 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
voi d
cr eat eDwg( )
{
AcDbDat abase *pDb = new AcDbDat abase( ) ;
AcDbBl ockTabl e *pBt bl ;
pDb- >get Symbol Tabl e( pBt bl , AcDb: : kFor Read) ;
AcDbBl ockTabl eRecor d *pBt bl Rcd;
pBt bl - >get At ( ACDB_MODEL_SPACE, pBt bl Rcd,
AcDb: : kFor Wr i t e) ;
pBt bl - >cl ose( ) ;
AcDbCi r cl e *pCi r 1 = new AcDbCi r cl e( AcGePoi nt 3d( 1, 1, 1) ,
AcGeVect or 3d( 0, 0, 1) ,
1. 0) ,
*pCi r 2 = new AcDbCi r cl e( AcGePoi nt 3d( 4, 4, 4) ,
AcGeVect or 3d( 0, 0, 1) ,
2. 0) ;
pBt bl Rcd- >appendAcDbEnt i t y( pCi r 1) ;
pCi r 1- >cl ose( ) ;
pBt bl Rcd- >appendAcDbEnt i t y( pCi r 2) ;
pCi r 2- >cl ose( ) ;
pBt bl Rcd- >cl ose( ) ;
/ / AcDbDat abase: : saveAs( ) does
aut omat i cal l y
/ / append a DWG f i l e ext ensi on, so i t
/ / must be speci f i ed.
/ /
pDb- >saveAs( _T( " c: \ \ t est 1. dwg" ) ) ;
del et e pDb;
}
voi d
r eadDwg( )
{
/ / Set const r uct or par amet er t o kFal se so t hat t he
/ / dat abase wi l l be const r uct ed empt y. Thi s way onl y
/ / what i s r ead i n wi l l be i n t he dat abase.
/ /
AcDbDat abase *pDb = new AcDbDat abase( Adesk: : kFal se) ;
/ / The AcDbDat abase: : r eadDwgFi l e( ) f unct i on
/ / aut omat i cal l y appends a DWG ext ensi on i f i t i s not
/ / speci f i ed i n t he f i l ename par amet er .
/ /
i f ( Acad: : eOk ! = pDb- >r eadDwgFi l e( _T( " c: \ \ t est 1. dwg" ) ) )
r et ur n;
/ / Open t he model space bl ock t abl e r ecor d.
/ /
AcDbBl ockTabl e *pBl kTbl ;
pDb- >get Symbol Tabl e( pBl kTbl , AcDb: : kFor Read) ;
AcDbBl ockTabl eRecor d *pBl kTbl Rcd;
pBl kTbl - >get At ( ACDB_MODEL_SPACE, pBl kTbl Rcd,
AcDb: : kFor Read) ;
pBl kTbl - >cl ose( ) ;
AcDbBl ockTabl eRecor dI t er at or *pBl kTbl RcdI t r ;
pBl kTbl Rcd- >newI t er at or ( pBl kTbl RcdI t r ) ;
AcDbEnt i t y *pEnt ;
f or ( pBl kTbl RcdI t r - >st ar t ( ) ; ! pBl kTbl RcdI t r - >done( ) ;
pBl kTbl RcdI t r - >st ep( ) )
{
pBl kTbl RcdI t r - >get Ent i t y( pEnt ,
AcDb: : kFor Read) ;
acut Pr i nt f ( " cl assname: %s\ n" ,
( pEnt - >i sA( ) ) - >name( ) ) ;
pEnt - >cl ose( ) ;
}
pBl kTbl Rcd- >cl ose( ) ;
del et e pBl kTbl RcdI t r ;
del et e pDb;
}
not
Page 51 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Long Transactions are used to support the AutoCAD Reference Editing feature and are very useful for
ObjectARX applications. These classes and functions provide a scheme for applications to check out
entities for editing and check them back in to their original location. This operation replaces the original
objects with the edited ones. There are three types of long transaction check out:
From a normal block within the same drawing
From an external reference (xref) of the drawing
From an unrelated, temporary database
Topics in this section
Long Transaction Class and Function Overview
Long Transaction Example
The main long transaction classes and functions are
AcDbLongTransaction class
AcDbLongTransWorkSetIterator class
AcApLongTransactionReactor class
AcApLongTransactionManager class
wblockCloneObjects function
AcDbLongTransaction Class
AcDbLongTr ansact i on is the class that contains the information needed to track a long
transaction. The AcDbLongTr ansact i onManager class takes the responsibility for creating and
appending AcDbLongTr ansact i on objects to the database. It then returns the AcDbObj ect I d of
the AcDbLongTr ansact i on object. Like all other database-resident objects, its destruction is
handled by the database.
Note The AcDbLongTr ansact i on objects are added to a database while they are active and are
erased once the transaction has completed. They are not stored in DWG or DXF files, and
therefore are not persistent.
AcDbLongTransWorkSetIterator Class
AcDbLongTr ansWor kSet I t er at or provides read-only access to the objects in the work set. During
construction in AcDbLongTr ansact i on: : newWor kSet I t er at or ( ) , it can be set up to include only
the active work set, or include objects added to the work set because they are referenced by
objects in the work set (secondary objects). It can also handle objects removed from the work
set, either by AcDbLongTr ansact i on: : r emoveFr omWor kSet ( ) , or by being erased.
AcApLongTransactionReactor Class
AcApLongTr ansact i onReact or provides notification specific to long transaction operations. It is
designed to be used in conjunction with the deep clone notifications that will also be sent, but will
vary depending upon which type of check out/in is being executed. To connect these notifications
with the deep clone notifications, the AcDbI dMappi ng object used for cloning can be retrieved by
calling the AcDbLongTr ansact i on: : act i veI dMap( ) function.
AcApLongTransactionManager Class
Long Transactions
Long Transaction Class and Function Overview
Page 52 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
AcApLongTr ansact i onManager is the manager for starting and controlling long transactions. There
is only one for each AutoCAD session, and it is accessed via a pointer returned by the
acapLongTr ansact i onManager object.
AcDbDatabase::wblockCloneObjects() Function
The wbl ockCl oneObj ect s( ) function is a member of AcDbDat ase. It will deep clone objects from
one database to another and follow hard references so that all dependent objects are also cloned.
The behavior of symbol table records, when duplicates are found, is determined by the type
parameter. The following chart shows the relationship between a symbol table type (enum
Dupl i cat eRecor dCl oni ng) and a deep clone type (enumDeepCl oneType).
This simple example shows how to check out entities from another database, modify them in the current
database, and then check them back in to the original database. The calls that are part of the long
transaction process are indicated in bold print.
Relationship between
DeepCloneTypes and
DuplicateRecordCloning
for different commands
and functions
Command or API
Function
DeepCloneType DuplicateRecordCloning
COPY kDcCopy kDrcNotApplicable
EXPLODE kDcExplode kDrcNotApplicable
BLOCK kDcBlock kDrcNotApplicable
INSERT/BIND kDcXrefInsert kDrcIgnore
XRESOLVE kDcSymTableMerge kDrcXrefMangleName
INSERT kDcInsert kDrcIgnore
insert() kDcInsertCopy kDrcIgnore
WBLOCK kDcWblock kDrcNotApplicable
deepCloneObjects() kDcObjects kDrcNotApplicable
wblockObjects() kDcObjects kDrcIgnore
wblockObjects() kDcObjects kDrcReplace
wblockObjects() kDcObjects kDrcMangleName
wblockObjects() kDcObjects kDrcUnmangleName
Long Transaction Example
Page 53 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
voi d
r ef Edi t Api Exampl e( )
{
AcDbObj ect I d t r ansI d;
AcDbDat abase* pDb;
TCHAR *f name;
st r uct r esbuf *r b;
/ / Get a dwg f i l e f r omt he user .
/ /
r b = acut NewRb( RTSTR) ;
i nt st at = acedGet Fi l eD( _T( " Pi ck a dr awi ng" ) , NULL, _T( " dwg" ) ,
0, r b) ;
i f ( ( st at ! = RTNORM) | | ( r b == NULL) ) {
acut Pr i nt f ( _T( " \ nYou must pi ck a dr awi ng f i l e. " ) ) ; r et ur n; }
f name = ( TCHAR*) acad_mal l oc( ( _t csl en( r b- >r esval . r st r i ng) + 1) *
si zeof ( TCHAR) ) ;
_t cscpy( f name, r b- >r esval . r st r i ng) ;
acut Rel Rb( r b) ;
/ / Open t he dwg f i l e.
/ /
pDb = new AcDbDat abase( Adesk: : kFal se) ;
i f ( pDb- >r eadDwgFi l e( f name) ! = Acad: : eOk) {
acut Pr i nt f ( _T( " \ nSor r y, t hat dr awi ng i s pr obabl y al r eady
open. " ) ) ;
r et ur n;
}
/ / Get t he Bl ock Tabl e and t hen t he model space r ecor d.
/ /
AcDbBl ockTabl e *pBl ockTabl e;
pDb- >get Symbol Tabl e( pBl ockTabl e, AcDb: : kFor Read) ;
AcDbBl ockTabl eRecor d *pOt her MsBt r ;
pBl ockTabl e- >get At ( ACDB_MODEL_SPACE, pOt her MsBt r ,
AcDb: : kFor Read) ;
pBl ockTabl e- >cl ose( ) ;
/ / Cr eat e an i t er at or .
/ /
AcDbBl ockTabl eRecor dI t er at or *pI t er ;
pOt her MsBt r - >newI t er at or ( pI t er ) ;
/ / Set up an obj ect I D ar r ay.
/ /
AcDbObj ect I dAr r ay obj I dAr r ay;
/ / I t er at e over t he model space BTR. Look speci f i cal l y
/ / f or l i nes and append t hei r obj ect I D t o t he ar r ay.
/ /
f or ( pI t er - >st ar t ( ) ; ! pI t er - >done( ) ; pI t er - >st ep( ) ) {
AcDbEnt i t y *pEnt i t y;
pI t er - >get Ent i t y( pEnt i t y, AcDb: : kFor Read) ;
/ / Look f or onl y AcDbLi ne obj ect s and add t hemt o t he
/ / obj ect I D ar r ay.
/ /
i f ( pEnt i t y- >i sKi ndOf ( AcDbLi ne: : desc( ) ) ) {
obj I dAr r ay. append( pEnt i t y- >obj ect I d( ) ) ;
}
pEnt i t y- >cl ose( ) ;
}
del et e pI t er ;
pOt her MsBt r - >cl ose( ) ;
i f ( obj I dAr r ay. i sEmpt y( ) ) {
acad_f r ee( f name) ;
acut Pr i nt f ( _T( " \ nYou must pi ck a dr awi ng f i l e t hat cont ai ns
l i nes. " ) ) ;
r et ur n;
}
/ / Now get t he cur r ent dat abase and t he obj ect I D f or t he
/ / cur r ent dat abase' s model space BTR.
/ /
AcDbBl ockTabl e *pThi sBl ockTabl e;
acdbHost Appl i cat i onSer vi ces( ) - >wor ki ngDat abase( ) - >
get Symbol Tabl e( pThi sBl ockTabl e, AcDb: : kFor Read) ;
AcDbBl ockTabl eRecor d *pThi sMsBt r ;
pThi sBl ockTabl e- >get At ( ACDB_MODEL_SPACE, pThi sMsBt r ,
AcDb: : kFor Wr i t e) ;
Page 54 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
External references (xrefs) can be created and manipulated through several global functions. These
global functions mimic the AutoCAD XREF command capabilities. The functions provided are
acedXr ef At t ach( )
acedXr ef Over l ay( )
acedXr ef Unl oad( )
acedXr ef Det ach( )
acedXr ef Resol ve( )
acedXr ef Bi nd( )
acedXr ef XBi nd( )
acedXr ef Cr eat eBl ockname( )
acedXr ef Rel oad( )
For information on the AutoCAD XREF command, see the AutoCAD User's Guide.
The main programming consideration concerning xrefs is that, for every xref that is attached to a
drawing, a separate database is created to represent the drawing containing the xref. A block table
record in the main drawing contains the name of the external drawing and points to the entities of the
model space of the externally referenced drawing. The xref database also contains other block table
records and symbol table entries required to resolve all references from the main block table record
(layers, linetypes, and so on).
You can create an editor reactor, as described in Notification, to monitor xref events. The
AcEdi t or React or class provides the following reactor callback functions:
begi nAt t ach( )
ot her At t ach( )
abor t At t ach( )
endAt t ach( )
r edi r ect ed( )
comandeer ed( )
begi nRest or e( )
abor t Rest or e( )
endRest or e( )
When using these functions, be careful to notice which database is being returned. Also, be aware that
the xref drawing can itself contain xrefs to additional drawings. For more information on the
AcEdi t or React or class, see the ObjectARX Reference.
Xref entities in a drawing can be modified, but they cannot be saved to the original xref drawing (the
original drawing is read-only).
Topics in this section
External Reference Pre- and Post-Processing
File Locking and Consistency Checks
External References
Page 55 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
External reference (xref) pre- and post-processing makes it possible to restore an attached xref's in-
memory AcDbDat abase so that it can be saved back to a file. During xref resolve, many symbol table
records are mangled, and some are erased. Historically, this was done to simplify the resolve process,
and was acceptable because the databases were read-only. This processing makes it possible to
temporarily reverse the resolve changes so that the xref database can be modified and written back to
its file.
The functions that aid in pre- and post-processing are added to AcDbDat abase. They include a utility
function to find the associated block table record from an xref database, as well as the ability to restore
the resolved xref, and to reset it back to the proper resolved condition after restoration.
The customary usage for these functions would be to do the restore to the original symbols, make the
modifications to the database, save the database, and then restore the forwarded symbols. These steps
must be written into a single block of code, to prevent attempts to regenerate the host drawing, execute
any xref commands, or provide user prompts while the xref database is in its restored condition.
The functions are
AcDbDat abase: : xr ef Bl ockI d( )
AcDbDat abase: : r est or eOr i gi nal Xr ef Symbol s( )
AcDbDat abase: : r est or eFor war di ngXr ef Symbol s( )
Topics in this section
AcDbDatabase::xrefBlockId() Function
AcDbDatabase::restoreOriginalXrefSymbols() Function
AcDbDatabase::restoreForwardingXrefSymbols() Function
The xr ef Bl ockI d( ) function will get the AcDbObj ect I d of the block table record, which refers to this
database as an xref. When an xref is reloaded for any reason (for example, XREF Reload or XREF Path
commands), the former database is kept in memory for Undo. This means that more than one database
may point to the same xref block table record. However only one will be the currently active xref
database for that record. The database pointer returned by the AcDbBl ockTabl eRecor d: : xr ef Dat abase
( ) function on the found record will be the active database for that xref.
The r est or eOr i gi nal Xr ef Symbol s( ) function restores a resolved xref database to its original form, as
it would be if just loaded from its file. The xref is then in a condition where it can be modified and saved
back to a file. After calling this function, the host drawing is no longer in a valid state for regen or for
any xref command modifications or reloads. The database modifications, save back, and the
r est or eFor war di ngXr ef Symbol s( ) function must be called before anything that might allow a regen.
External Reference Pre- and Post-Processing
AcDbDatabase::xrefBlockId() Function
AcDbDatabase::restoreOriginalXrefSymbols() Function
AcDbDatabase::restoreForwardingXrefSymbols() Function
Page 56 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
The r est or eFor war di ngXr ef Symbol s( ) function restores the xref back to a valid, attached state. Not
only does it restore the original resolved symbols, but it also seeks out newly added symbols and
resolves them as well. The r est or eFor war di ngXr ef Symbol s( ) function cannot handle newly added,
nested xref block table records unless they already exist and are resolved in the host drawing.
The AcEdXr ef Fi l eLock base class is provided to handle the management of xref file locking. Its main
purpose is to prepare the xref block in a drawing for in-place editing, though, it can be used for other
purposes. It is assumed that these xref file methods operate on the current database drawing.
The acedXr ef Rel oad( ) global function processes the list of xref block table record object IDs for xref
reload. It is assumed that each xref block table record object ID references an xref drawing file that can
be reloaded to the current drawing. It has the same functionality as the AutoCAD XREF subcommand for
Reload.
The index and filter classes and functions provide a scheme for applications to define custom indexes
and custom filtering of block data. An application can define its custom implementations of AcDbFi l t er ,
AcDbI ndex, and AcDbFi l t er edBl ockI t er at or . It will register the AcDbFi l t er with a block reference
through AcI ndexFi l t er Manager : : addFi l t er ( ) , and an AcDbI ndex with the corresponding block table
record through AcI ndexFi l t er Manager : : addI ndex( ) . After that, regens of xrefs and blocks will respect
the query defined by the AcDbFi l t er , and use the AcDbFi l t er edBl ockI t er at or to decide what object
IDs will be processed during regen. The indexes will be kept up to date through either the application
explicitly calling AcI ndexFi l t er Manager : : updat eI ndexes( ) , or the application can rely on the AutoCAD
save operation calling AcI ndexFi l t er Manager : : updat eI ndexes( ) on the AcDbDat abase being saved.
The AcDbI ndex: : r ebui l dFul l ( ) or the AcDbI ndex: : r ebui l dModi f i ed( ) gets invoked during the
AcI ndexFi l t er Manager : : updat eI ndexes( ) call.
A current use of the indexing scheme in AutoCAD is fast demand loading of clipped xrefs. A spatial index
(an AcDbSpat i al I ndex object) is stored in the xrefed drawing. An AcDbSpat i al Fi l t er object defines
the clip volume of the block reference to the xref in the host drawing. When demand loading is turned
on for the xref, the spatial filter volume is used to traverse the xref data through the spatial index, in
order to page in from the DWG file only those entities whose graphics intersect the clip volume.
These classes and functions provide an interface for:
Updating indexes
Adding and removing indexes to block table records
Adding and removing filters to block references
Querying for indexes from block table records
Querying for filters from block references
Iterating through block table records and visiting only a subset of entities
Topics in this section
Index and Filter Class and Function Overview
File Locking and Consistency Checks
Indexes and Filters
Index and Filter Class and Function Overview
Page 57 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
The main index and filter classes and functions are
AcDbIndexFilterManager namespace
AcDbIndex class
AcDbFilter class
AcDbFilteredBlockIterator class
AcDbCompositeFilteredBlockIterator class
AcDbIndexFilterManager Namespace
The AcDbI ndexFi l t er Manager namespace is a collection of functions that provides index and filter
access and maintenance functionality.
AcDbIndex Class
The AcDbI ndex class is the base class for all index objects. AcDbSpat i al I ndex and
AcDbLayer I ndex derive from this class.
Keeping the index up to date is achieved through the AcDbI ndexFi l t er Manager : : updat eI ndexes
( ) function calls being explicitly invoked (either by an application or AutoCAD).
The AcDbFi l t er edBl ockI t er at or will serve as the means to visit all the AcDbObj ect I ds that are
hits from the query defined by the AcDbFi l t er passed to its constructor. For example, in the
spatial index case, the AcDbSpat i al Fi l t er object instance passed to the newI t er at or ( ) method
will define a query region. The AcDbSpat i al I ndex object, through its newI t er at or ( ) method, will
provide an AcDbSpat i al I ndexI t er at or that will return object IDs that correspond to entities that
fit within the query volume.
AcDbFilter Class
The AcDbFi l t er class is meant to define a query. It provides the key to the
AcDbComposi t eFi l t er edBl ockI t er at or , for which the corresponding index is obtained through
the i ndexCl ass( ) method.
AcDbFilteredBlockIterator Class
The AcDbFi l t er edBl ockI t er at or class provides a method to process a query on an index. It is
used by the AcDbComposi t eFi l t er edBl ockI t er at or .
AcDbCompositeFilteredBlockIterator Class
The AcDbComposi t eFi l t er edBl ockI t er at or class provides the alternate to normal block
iteration. By providing the filter list in the i ni t ( ) method, the
AcDbComposi t eFi l t er edBl ockI t er at or object looks for corresponding AcDbI ndex derived objects
through the AcDbFi l t er : : i ndexCl ass( ) method, and creates AcDbFi l t er edBl ockI t er at or
objects. If the matching up-to-date i ndexCl ass( ) objects are not available, it creates an
AcDbFi l t er edBl ockI t er at or through the AcDbFi l t er : : newI t er at or ( ) method. It then orders
the composition of the AcDbFi l t er edBl ockI t er at or objects based on the
AcDbFi l t er edBl ockI t er at or : : est i mat edHi t s( ) and
AcDbFi l t er edBl ockI t er at or : : buf f er sFor Composi t i on( ) methods. The collection of filters is a
conjunction of conditions. This means an object ID is output from the iterator only if the accept s
( ) method of each filter would accept the object ID.
The Drawing Property dialog allows AutoCAD users to embed ancillary data (called summary
information) in their DWG files, and assists in retrieving DWG files based on this data. This provides
AutoCAD users with base-level file retrieval and management capabilities.
Through Windows Explorer, the properties of a drawing can be viewed outside of AutoCAD. Used in
conjunction with the AutoCAD DesignCenter Advanced Find feature, summary information allows users
to search for drawings containing predefined or custom data.
Drawing Summary Information
Page 58 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Topics in this section
Drawing Summary Information Class and Function Overview
The main drawing summary information classes and functions are
AcDbDatabaseSummaryInfo class
AcDbSummaryInfoReactor class
AcDbSummaryInfoManager class
Global summary information functions
AcDbDatabaseSummaryInfo Class
The AcDbDat abaseSummar yI nf o class encapsulates a set of character strings that can be used to
add additional information to a DWG file. This information is stored and retrieved in the Summary
Information object with specific methods for each information field. The predefined fields are
Title
Subject
Author
Keywords
Comments
Last saved by
Revision number
Hyperlink base
You can create your own custom fields in addition to the predefined fields. These custom fields are
stored in a list, and you can manipulate custom fields either by their name (or key) or position
(index) in the list. Custom fields are indexed starting at 1, and there is no limit to the number of
fields you can create.
AcDbSummaryInfoReactor Class
This class provides a reactor to let you know if the summary information is changed.
AcDbSummaryInfoManager Class
The AcDbSummar yI nf oManager class organizes the summary information reactors, with methods to
add and remove reactors, and to send notification that the summary information has changed.
Global Summary Information Functions
ObjectARX contains several global functions for accessing summary information:
acdbGetSummaryInfo
acdbPutSummaryInfo
acdbSummaryInfoManager
The dwgFileWasSavedByAutodeskSoftware method returns true if it determines that the database was
last saved by Autodesk software (such as AutoCAD or AutoCAD LT
).
Drawing Summary Information Class and Function Overview
Last Saved by Autodesk Software
Page 59 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
This section describes topics that relate to all AutoCAD
or AutoLISP
and can be
added to any object. Xdata consists of a linked list of resbufs used by the application. (AutoCAD
maintains the information but doesn't use it.) The data is associated with a DXF group code in the range
of 1000 to 1071.
This mechanism is space-efficient and can be useful for adding lightweight data to an object. However,
xdata is limited to 16K and to the existing set of DXF group codes and types.
For a more detailed description of xdata, see the AutoCAD DXF Reference.
Use the AcDbObj ect : : xDat a( ) function to obtain the resbuf chain containing a copy of the xdata for an
object:
Use the AcDbObj ect : : set XDat a( ) function to specify the xdata for an object:
The following example uses the xDat a( ) function to obtain the xdata for a selected object and then
prints the xdata to the screen. It then adds a string (t est r un) to the xdata and calls the set Xdat a( )
function to modify the object's xdata. This example also illustrates the use of the upgr adeOpen( ) and
downgr adeOpen( ) functions.
Extended Data
vi r t ual r esbuf *
AcDbObj ect : : xDat a( const char * r egappName = NULL) const ;
vi r t ual Acad: : Er r or St at us
AcDbObj ect : : set XDat a( const r esbuf * xdat a) ;
Page 63 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
/ / Thi s f unct i on cal l s t he sel ect Obj ect ( ) f unct i on t o al l ow
/ / t he user t o pi ck an obj ect ; t hen i t accesses t he xdat a of
/ / t he obj ect and sends t he l i st t o t he pr i nt Li st ( ) f unct i on
/ / t hat l i st s t he r est ype and r esval val ues.
/ /
voi d
pr i nt Xdat a( )
{
/ / Sel ect and open an obj ect .
/ /
AcDbObj ect *pObj ;
i f ( ( pObj = sel ect Obj ect ( AcDb: : kFor Read) ) == NULL) {
r et ur n;
}
/ / Get t he appl i cat i on name f or t he xdat a.
/ /
char appname[ 133] ;
i f ( acedGet St r i ng( NULL,
" \ nEnt er t he desi r ed Xdat a appl i cat i on name: " ,
appname) ! = RTNORM)
{
r et ur n;
}
/ / Get t he xdat a f or t he appl i cat i on name.
/ /
st r uct r esbuf *pRb;
pRb = pObj - >xDat a( appname) ;
i f ( pRb ! = NULL) {
/ / Pr i nt t he exi st i ng xdat a i f any i s pr esent .
/ / Not i ce t hat t her e i s no - 3 gr oup, as t her e i s i n
/ / LI SP. Thi s i s ONLY t he xdat a, so
/ / t he - 3 xdat a- st ar t mar ker i sn' t needed.
/ /
pr i nt Li st ( pRb) ;
acut Rel Rb( pRb) ;
} el se {
acut Pr i nt f ( " \ nNo xdat a f or t hi s appname" ) ;
}
pObj - >cl ose( ) ;
}
voi d
addXdat a( )
{
AcDbObj ect * pObj = sel ect Obj ect ( AcDb: : kFor Read) ;
i f ( ! pObj ) {
acut Pr i nt f ( " Er r or sel ect i ng obj ect \ n" ) ;
r et ur n;
}
/ / Get t he appl i cat i on name and st r i ng t o be added t o
/ / xdat a.
/ /
char appName[ 132] , r esSt r i ng[ 200] ;
appName[ 0] = r esSt r i ng[ 0] = ' \ 0' ;
acedGet St r i ng( NULL, " Ent er appl i cat i on name: " ,
appName) ;
acedGet St r i ng( NULL, " Ent er st r i ng t o be added: " ,
r esSt r i ng) ;
st r uct r esbuf *pRb, *pTemp;
pRb = pObj - >xDat a( appName) ;
i f ( pRb ! = NULL) {
/ / I f xdat a i s pr esent , t hen wal k t o t he
/ / end of t he l i st .
/ /
f or ( pTemp = pRb; pTemp- >r bnext ! = NULL;
pTemp = pTemp- >r bnext )
{ ; }
} el se {
/ / I f xdat a i s not pr esent , r egi st er t he appl i cat i on
/ / and add appName t o t he f i r st r esbuf i n t he l i st .
/ / Not i ce t hat t her e i s no - 3 gr oup as t her e i s i n
/ / Aut oLI SP. Thi s i s ONLY t he xdat a so
/ / t he - 3 xdat a- st ar t mar ker i sn' t needed.
Page 64 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Every object can have an extension dictionary, which can contain an arbitrary set of AcDbObj ect
objects. Using this mechanism, several applications can attach data to the same object. The extension
dictionary requires more overhead than xdata, but it also provides a more flexible mechanism with
higher capacity for adding data.
For an example of using an extension dictionary to attach an arbitrary string to any AcDbObj ect , see the
edinvent program in the ObjectARX samples\database\dataxtsn directory.
Topics in this section
ObjectARX Extension Dictionary Example
Global Function Extension Dictionary Example
The following example shows instantiating an xrecord and adding it to an extension dictionary in the
named object dictionary:
Extension Dictionary
ObjectARX Extension Dictionary Example
Page 65 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
voi d
cr eat eXr ecor d( )
{
AcDbXr ecor d *pXr ec = new AcDbXr ecor d;
AcDbObj ect *pObj ;
AcDbObj ect I d di ct Obj I d, xr ecObj I d;
AcDbDi ct i onar y* pDi ct ;
pObj = sel ect Obj ect ( AcDb: : kFor Wr i t e) ;
i f ( pObj == NULL) {
r et ur n;
}
/ / Tr y t o cr eat e an ext ensi on di ct i onar y f or t hi s
/ / obj ect . I f t he ext ensi on di ct i onar y al r eady exi st s,
/ / t hi s wi l l be a no- op.
/ /
pObj - >cr eat eExt ensi onDi ct i onar y( ) ;
/ / Get t he obj ect I D of t he ext ensi on di ct i onar y f or t he
/ / sel ect ed obj ect .
/ /
di ct Obj I d = pObj - >ext ensi onDi ct i onar y( ) ;
pObj - >cl ose( ) ;
/ / Open t he ext ensi on di ct i onar y and add t he new
/ / xr ecor d t o i t .
/ /
acdbOpenObj ect ( pDi ct , di ct Obj I d, AcDb: : kFor Wr i t e) ;
pDi ct - >set At ( " ASDK_XREC1" , pXr ec, xr ecObj I d) ;
pDi ct - >cl ose( ) ;
/ / Cr eat e a r esbuf l i st t o add t o t he xr ecor d.
/ /
st r uct r esbuf * head;
ads_poi nt t est pt = {1. 0, 2. 0, 0. 0};
head = acut Bui l dLi st ( AcDb: : kDxf Text ,
" Thi s i s a t est Xr ecor d l i st " ,
AcDb: : kDxf XCoor d, t est pt ,
AcDb: : kDxf Real , 3. 14159,
AcDb: : kDxf Angl e, 3. 14159,
AcDb: : kDxf Col or , 1,
AcDb: : kDxf I nt 16, 180,
0) ;
/ / Add t he dat a l i st t o t he xr ecor d. Not i ce t hat t hi s
/ / member f unct i on t akes a r ef er ence t o a r esbuf NOT a
/ / poi nt er t o a r esbuf , so you must der ef er ence t he
/ / poi nt er bef or e sendi ng i t .
/ /
pXr ec- >set Fr omRbChai n( *head) ;
pXr ec- >cl ose( ) ;
acut Rel Rb( head) ;
}
/ / The l i st Xr ecor d( ) f unct i on get s t he xr ecor d associ at ed wi t h t he
/ / key " ASDK_XREC1" and l i st s out i t s cont ent s by passi ng t he r esbuf
/ / l i st t o t he f unct i on pr i nt Li st ( ) .
/ /
voi d
l i st Xr ecor d( )
{
AcDbObj ect *pObj ;
AcDbXr ecor d *pXr ec;
AcDbObj ect I d di ct Obj I d;
AcDbDi ct i onar y *pDi ct ;
pObj = sel ect Obj ect ( AcDb: : kFor Read) ;
i f ( pObj == NULL) {
r et ur n;
}
/ / Get t he obj ect I D of t he obj ect ' s ext ensi on di ct i onar y.
/ /
di ct Obj I d = pObj - >ext ensi onDi ct i onar y( ) ;
pObj - >cl ose( ) ;
/ / Open t he ext ensi on di ct i onar y and get t he xr ecor d
/ / associ at ed wi t h t he key ASDK_XREC1.
/ /
acdbOpenObj ect ( pDi ct , di ct Obj I d, AcDb: : kFor Read) ;
pDi ct - >get At ( " ASDK_XREC1" , ( AcDbObj ect *&) pXr ec,
Page 66 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
The following example uses global ObjectARX functions to create an xrecord and add it to the dictionary
associated with the key ASDK_REC.
Global Function Extension Dictionary Example
Page 67 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
i nt
cr eat eXr ecor d( )
{
st r uct r esbuf *pXr ec, *pEnt , *pDi ct , *pTemp, *pTemp2;
ads_poi nt dummy, t est pt = {1. 0, 2. 0, 0. 0};
ads_name xr ecname, ename, ext Di ct = {0L, 0L};
/ / Have t he user sel ect an ent i t y. Then get i t s dat a.
/ /
i f ( acedEnt Sel ( " \ nsel ect ent i t y: " , ename, dummy)
! = RTNORM)
{
acut Pr i nt f ( " \ nNot hi ng sel ect ed" ) ;
acedRet Voi d( ) ;
r et ur n RTNORM;
}
pEnt = acdbEnt Get ( ename) ;
/ / Now check t o see i f t he ent i t y al r eady has an
/ / ext ensi on di ct i onar y.
/ /
f or ( pTemp = pEnt ; pTemp- >r bnext ! = NULL;
pTemp = pTemp- >r bnext )
{
i f ( pTemp- >r est ype == 102) {
i f ( ! st r cmp( " {ACAD_XDI CTI ONARY" ,
pTemp- >r esval . r st r i ng) )
{
ads_name_set ( pTemp- >r bnext - >r esval . r l name, ext Di ct ) ;
br eak;
}
}
}
/ / I f no ext ensi on di ct i onar y exi st s, add one.
/ /
i f ( ext Di ct [ 0] == 0L) {
pDi ct = acut Bui l dLi st ( RTDXF0, " DI CTI ONARY" , 100,
" AcDbDi ct i onar y" , 0) ;
acdbEnt MakeX( pDi ct , ext Di ct ) ;
acut Rel Rb( pDi ct ) ;
pDi ct = acut Bui l dLi st ( 102, " {ACAD_XDI CTI ONARY" , 360,
ext Di ct , 102, " }" , 0) ;
f or ( pTemp = pEnt ; pTemp- >r bnext - >r est ype ! = 100;
pTemp = pTemp- >r bnext )
{ ; }
f or ( pTemp2 = pDi ct ; pTemp2- >r bnext ! = NULL;
pTemp2 = pTemp2- >r bnext )
{ ; }
pTemp2- >r bnext = pTemp- >r bnext ;
pTemp- >r bnext = pDi ct ;
acdbEnt Mod( pEnt ) ;
acut Rel Rb( pEnt ) ;
}
/ / At t hi s poi nt t he ent i t y has an ext ensi on di ct i onar y.
/ / Cr eat e a r esbuf l i st of t he xr ecor d' s ent i t y i nf or mat i on
/ / and dat a.
/ /
pXr ec = acut Bui l dLi st ( RTDXF0, " XRECORD" ,
100, " AcDbXr ecor d" ,
1, " Thi s i s a t est Xr ecor d l i st " , / / AcDb: : kDxf Text
10, t est pt , / / AcDb: : kDxf XCoor d
40, 3. 14159, / / AcDb: : kDxf Real
50, 3. 14159, / / AcDb: : kDxf Angl e
60, 1, / / AcDb: : kDxf Col or
70, 180, / / AcDb: : kDxf I nt 16
0) ;
/ / Cr eat e t he xr ecor d wi t h no owner set . The xr ecor d' s
/ / new ent i t y name wi l l be pl aced i nt o t he xr ecname
/ / ar gument .
/ /
acdbEnt MakeX ( pXr ec, xr ecname) ;
acut Rel Rb ( pXr ec) ;
/ / Set t he xr ecor d' s owner t o t he ext ensi on di ct i onar y
/ /
Page 68 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Any object in the database can be erased with the following function:
Note The er ase( ) function has different results for database objects and entities, with consequences
for unerasing them:
When a database object is erased, information about that object is removed from the dictionary. If
the object is unerased with er ase( kf al se) , the information is not automatically reintroduced. You
must use the set At ( ) function to add the information to the dictionary again.
When an entity is erased, it is simply flagged as erased in the block table record. The entity can be
unerased with er ase( kf al se) .
By default, you cannot open an erased object with the acdbOpenObj ect ( ) function. If you attempt to do
so, the eWasEr ased error code will be returned.
To open an erased object, use kTr ue for the last parameter of the acdbOpenObj ect ( ) function.
Container objects such as polylines and block table records usually provide the option of skipping erased
elements when iterating over their contents. The default behavior is to skip erased elements.
Erased objects are not filed out to DWG or DXF files.
Object filing refers to the conversion process between an object's state and a single sequence of data,
for purposes such as storing it on disk, copying it, or recording its state for an undo operation. Filing out
is sometimes called serializing. Filing an object in is the process of turning a sequence of data back into
an object, sometimes called deserializing.
Filing is used in several contexts in AutoCAD:
Writing and reading DWG files (uses DWG format)
Writing and reading DXF files (uses DXF format)
Communicating among AutoCAD, AutoLISP, and ObjectARX (uses DXF format)
Undo recording and restoring (uses DWG format)
Copying operations such as INSERT, XREF, and COPY (uses DWG format)
Paging (uses DWG format)
AcDbObj ect has two member functions for filing out: dwgOut ( ) and dxf Out ( ) , and two member
functions for filing in: dwgI n( ) and dxf I n( ) . These member functions are primarily called by AutoCAD;
Erasing Objects
Acad: : Er r or St at us
AcDbObj ect : : er ase(
Adesk: : Bool ean Er asi ng = t r ue) ;
ext er n Acad: : Er r or St at us
acdbOpenObj ect (
AcDbObj ect *& obj ,
AcDbObj ect I d obj I d,
AcDb: : OpenMode openMode,
Adesk: : Bool ean openEr asedObj ect = Adesk: : kFal se) ;
Object Filing
Page 69 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
object filing is almost never explicitly controlled by applications that use the database. However, if your
application implements new database object classes, you'll need a more in-depth understanding of
object filing. See Deriving from AcDbObject
The dwg- and dxf - prefixes indicate two fundamentally different data formats, the first typically used in
writing to and from DWG files, and the second primarily for DXF files and AutoLISP ent get , ent make,
and ent mod functions. The primary difference between the two formats is that for DWG filers (an object
that writes data to a file), the data is not explicitly tagged. The DXF filers, in contrast, associate a data
group code with every element of data in a published data format (see Deriving from AcDbObject).
There are two ways in which an object can be embedded in another object: either the encapsulating
object has a data member that is an actual embedded object, or the encapsulating object has a pointer
to an object (in which case the object is considered to be embedded). In either case, the encapsulating
object is responsible for allocating and deallocating the embedded object. The encapsulating object must
also forward all calls to the embedded object's methods because AutoCAD is unaware of the embedded
object. In order to display the embedded object, the encapsulating object's subWor l dDr aw( ) must make
a call to the embedded object's wor l dDr aw( ) .
For subGet Gr i pPoi nt s( ) and subGet St r et chPoi nt s( ) , you must call the embedded object's
get Gr i pPoi nt s( ) and get St r et chPoi nt s( ) methods last so that its points end up with indices higher
than those of the encapsulating entity. Then, in subMoveGr i pPoi nt sAt ( ) and subMoveSt r et chPoi nt sAt
( ) , if any of the indices passed in are above the range of those of the encapsulating entity, you subtract
the highest index value of the encapsulating entity and pass the result into the embedded object's
moveGr i pPoi nt sAt ( ) or moveSt r et chPoi nt sAt ( ) . For example, the following code from a version of the
jblob sample has been updated to have an embedded AcDbCi r cl e entity:
Embedded and Encapsulating Objects
Page 70 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
For filing purposes, the encapsulating object must call the embedded object's dwgOut Fi el ds( ) ,
dwgI nFi el ds( ) , dxf Out Fi el ds( ) , and dxf I nFi el ds( ) methods from within its own version of these
methods.
Acad: : Er r or St at us
J bl ob: : subGet Gr i pPoi nt s(
AcGePoi nt 3dAr r ay& gr i pPoi nt s,
AcDbI nt Ar r ay& osnapMasks,
AcDbI nt Ar r ay& geomI ds) const
{
asser t ReadEnabl ed( ) ;
gr i pPoi nt s. append( mp) ;
gr i pPoi nt s. append( mp + 0. 5 * ( mpbl ob - mp) ) ;
gr i pPoi nt s. append( mpbl ob) ;
AcGeVect or 3d xof f ( mr bl ob, 0, 0) ;
AcGeVect or 3d yof f ( 0, mr bl ob, 0) ;
gr i pPoi nt s. append( mpbl ob + xof f ) ;
gr i pPoi nt s. append( mpbl ob + yof f ) ;
gr i pPoi nt s. append( mpbl ob - xof f ) ;
gr i pPoi nt s. append( mpbl ob - yof f ) ;
r et ur n ci r cl e. get Gr i pPoi nt s( gr i pPoi nt s, osnapMasks, geomI ds) ;
}
Acad: : Er r or St at us
J bl ob: : subMoveGr i pPoi nt sAt (
const AcDbI nt Ar r ay& i ndi ces,
const AcGeVect or 3d& of f set )
{
AcGePoi nt 3d ol dquad, newquad;
asser t Wr i t eEnabl ed( ) ;
AcDbI nt Ar r ay ci r cl eI ndi ces;
f or ( i nt i = 0; i &l t ; i ndi ces. l engt h( ) ; i ++) {
i nt i dx = i ndi ces[ i ] ;
swi t ch( i dx) {
case 0:
mp += of f set ;
cont i nue; / / st r et ch begi n poi nt
case 1:
mp += of f set ;
mpbl ob += of f set ;
cont i nue; / / move
case 2:
mpbl ob += of f set ;
cont i nue; / / st r et ch bl ob cent er
/ / st r et ch bl ob r adi us:
/ /
case 3:
ol dquad = mpbl ob + AcGeVect or 3d( mr bl ob, 0, 0) ;
br eak;
case 4:
ol dquad = mpbl ob + AcGeVect or 3d( 0, mr bl ob, 0) ;
br eak;
case 5:
ol dquad = mpbl ob - AcGeVect or 3d( mr bl ob, 0, 0) ;
br eak;
case 6:
ol dquad = mpbl ob - AcGeVect or 3d( 0, mr bl ob, 0) ;
br eak;
def aul t :
i f ( i dx > 6)
ci r cl eI ndi ces. append( i dx - 7) ;
cont i nue;
}
newquad = ol dquad + of f set ;
mr bl ob = newquad. di st anceTo( mpbl ob) ;
}
i f ( ci r cl eI ndi ces. l engt h( ) > 0)
r et ur n ci r cl e. moveGr i pPoi nt sAt ( ci r cl eI ndi ces, of f set ) ;
el se
r et ur n Acad: : eOk;
}
Page 71 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
For DWG filing, the call to the embedded object's dwgOut Fi el ds( ) and dwgI nFi el ds( ) methods can
occur at any point in the corresponding methods of the encapsulating object (after the call to the base
class's method). However, the call must occur in the same place in both dwgOut Fi el ds( ) and
dwgI nFi el ds( ) . The following code is from the updated jblob sample program:
For DXF filing, the embedded object must be filed out and in after all the data of the encapsulating
object has been filed out and in; therefore, the call to the embedded object's dxf Out Fi el ds( ) and
dxf I nFi el ds( ) methods should come last in the encapsulating object's dxf Out Fi el ds( ) and
dxf I nFi el ds( ) methods. A separator is needed between the encapsulating object's data and the
subsequent embedded object's data. The separator must be similar in function to the group 0 or 100 in
that it must cause the filer to stop reading data. The normal DXF group code 0 cannot be used because
DXF proxies use it to determine when to stop reading data. The group code 100 could have been used,
but it might have caused confusion when manually reading a DXF file, and there was a need to
distinguish when an embedded object is about to be written out in order to do some internal
bookkeeping. Therefore, the DXF group code 101 was introduced.
The AcDb: : Dxf Code enum value for DXF group code 101 is AcDb: : kDxf EmbeddedObj ect St ar t . The data
string Embedded Obj ect is written out by the filer for this DXF group code.
Two methods were also added to the AcDbDxf Fi l er class:
writeEmbeddedObjectStart
atEmbeddedObjectStart
The following code demonstrates how these methods are used in the updated jblob sample program:
Acad: : Er r or St at us
J bl ob: : dwgI nFi el ds( AcDbDwgFi l er * f i l er )
{
asser t Wr i t eEnabl ed( ) ;
AcDbEnt i t y: : dwgI nFi el ds( f i l er ) ;
f i l er - >r eadI t em( &mp) ;
f i l er - >r eadI t em( &mpbl ob) ;
f i l er - >r eadI t em( &mr bl ob) ;
f i l er - >r eadI t em( &mnor mal ) ;
r et ur n ci r cl e. dwgI nFi el ds( f i l er ) ;
}
Acad: : Er r or St at us
J bl ob: : dwgOut Fi el ds( AcDbDwgFi l er * f i l er ) const
{
asser t ReadEnabl ed( ) ;
AcDbEnt i t y: : dwgOut Fi el ds( f i l er ) ;
f i l er - >wr i t eI t em( mp) ;
f i l er - >wr i t eI t em( mpbl ob) ;
f i l er - >wr i t eI t em( mr bl ob) ;
f i l er - >wr i t eI t em( mnor mal ) ;
r et ur n ci r cl e. dwgOut Fi el ds( f i l er ) ;
}
Page 72 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
The following example shows the output in a DXF file (with the 310 group data strings shortened for
readability):
Acad: : Er r or St at us
J bl ob: : dxf I nFi el ds( AcDbDxf Fi l er * f i l er )
{
asser t Wr i t eEnabl ed( ) ;
st r uct r esbuf r b;
Acad: : Er r or St at us es = AcDbEnt i t y: : dxf I nFi el ds( f i l er ) ;
i f ( es ! = Acad: : eOk) {
r et ur n es;
}
i f ( ! f i l er - >at Subcl assDat a( kCl assName) ) {
r et ur n Acad: : eBadDxf Sequence;
}
mnor mal = AcGeVect or 3d( 0, 0, 1) ; / / set def aul t val ue:
whi l e ( es == Acad: : eOk) {
i f ( ( es = f i l er - >r eadI t em( &r b) ) == Acad: : eOk) {
swi t ch( r b. r est ype) {
case AcDb: : kDxf XCoor d:
mp. set ( r b. r esval . r poi nt [ X] , r b. r esval . r poi nt [ Y] ,
r b. r esval . r poi nt [ Z] ) ;
br eak;
case AcDb: : kDxf XCoor d+1:
mpbl ob. set ( r b. r esval . r poi nt [ X] , r b. r esval . r poi nt [ Y] ,
r b. r esval . r poi nt [ Z] ) ;
br eak;
case AcDb: : kDxf Real :
mr bl ob = r b. r esval . r r eal ;
br eak;
case AcDb: : kDxf Nor mal X:
mnor mal . set ( r b. r esval . r poi nt [ X] , r b. r esval . r poi nt [ Y] ,
r b. r esval . r poi nt [ Z] ) ;
}
}
}
i f ( f i l er - >at EmbeddedObj ect St ar t ( ) )
r et ur n ci r cl e. dxf I nFi el ds( f i l er ) ;
el se {
f i l er - >set Er r or ( Acad: : eMi ssi ngDxf Fi el d,
" mi ssi ng expect ed embeddedObj ect mar ker " ) ;
r et ur n f i l er - >f i l er St at us( ) ;
}
}
Acad: : Er r or St at us
J bl ob: : dxf Out Fi el ds( AcDbDxf Fi l er * f i l er ) const
{
asser t ReadEnabl ed( ) ;
AcDbEnt i t y: : dxf Out Fi el ds( f i l er ) ;
f i l er - >wr i t eI t em( AcDb: : kDxf Subcl ass, kCl assName) ;
f i l er - >wr i t eI t em( AcDb: : kDxf XCoor d, mp) ;
f i l er - >wr i t eI t em( AcDb: : kDxf XCoor d + 1, mpbl ob) ;
f i l er - >wr i t eI t em( AcDb: : kDxf Real , mr bl ob) ;
i f ( f i l er - >i ncl udesDef aul t Val ues( )
| | mnor mal ! = AcGeVect or 3d( 0, 0, 1) )
{
f i l er - >wr i t eI t em( AcDb: : kDxf Nor mal X, mnor mal ) ;
}
f i l er - >wr i t eEmbeddedObj ect St ar t ( ) ;
r et ur n ci r cl e. dxf Out Fi el ds( f i l er ) ;
}
Page 73 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
This section describes entitiesdatabase objects with a graphical representation. It lists the properties
and operations all entities have in common. Examples show how to create blocks, inserts, and complex
entities, and how to select and highlight subentities.
Topics in this section
Entities Defined
Entity Ownership
Common Entity Properties
Common Entity Functions
Creating Instances of AutoCAD Entities
Complex Entities
0
J BLOB
5
52
330
19
100
AcDbEnt i t y
8
0
92
256
310
00010000040000003C0000000600000002000000. . .
310
000000000000000000000000000000F03F700000. . .
310
0000
100
J bl ob
10
4. 026791
20
3. 172968
30
0. 0
11
5. 916743
21
5. 299622
31
0. 0
40
1. 458724
101
Embedded Obj ect
100
AcDbEnt i t y
100
AcDbCi r cl e
10
5. 916743
20
5. 299622
30
0. 0
40
0. 729362
Entities
Page 74 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Coordinate System Access
Curve Functions
Associating Hyperlinks with Entities
An entity is a database object that has a graphical representation. Examples of entities include lines,
circles, arcs, text, solids, regions, splines, and ellipses. The AcDbEnt i t y class is derived from
AcDbObj ect . For a complete class hierarchy diagram, see classmap.dwg in the ObjectARX classmap
directory.
With a few exceptions, entities contain all necessary information about their geometry. A few entities
contain other objects that hold their geometric information or attributes. Complex entities include the
following:
AcDb2dPol yl i ne, which owns AcDb2dVer t ex objects
AcDb3dPol yl i ne, which owns AcDb3dPol yl i neVer t ex objects
AcDbPol ygonMesh, which owns AcDbPol ygonMeshVer t ex objects
AcDbPol yFaceMesh, which owns AcDbPol yFaceMeshVer t ex objects and AcDbFaceRecor d objects
AcDbBl ockRef er ence, which owns AcDbAt t r i but e objects
AcDbMI nser t Bl ock, which owns AcDbAt t r i but e objects
Examples of creating and iterating through complex entities are provided in Complex Entities.
Entities in the database normally belong to an AcDbBl ockTabl eRecor d. The block table in a newly
created database has three predefined records, *MODEL_SPACE, *PAPER_SPACE, and *PAPER_SPACE0,
which represent model space and the two pre-defined paper space layouts. Additional records are added
whenever the user creates new blocks (block records), typically by issuing a BLOCK, HATCH, or
DIMENSION command.
The ownership structure for database entities is as follows:
Entities Defined
Entity Ownership
Page 75 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
All entities have a number of common properties and include member functions for setting and getting
their values. These properties, which can also be set by user commands, are the following:
Color
Linetype
Linetype scale
Visibility
Layer
Line weight
Plot style name
When you add an entity to a block table record, AutoCAD
allows you to associate hyperlinks with entities, by using the classes AcDbHyper l i nk,
AcDbHyper l i nkCol l ect i on, and AcDbEnt i t yHyper l i nkPE. A hyperlink can be a URL or a non-Web
address such as a local file. You can attach, view, edit, and list hyperlinks within your application.
Topics in this section
Hyperlink Class Overview
Hyperlink Example
The main hyperlink classes are
AcDbHyperlink class
AcDbHyperlinkCollection class
AcDbEntityHyperlinkPE class
AcDbHyperlink Class
An AcDbHyper l i nk object contains the hyperlink name (for example, http://www.autodesk.com),
a sublocation within that link, the hyperlink description or friendly name (Click here for
Autodesk), and a display string for the hyperlink. For AutoCAD, a sublocation is a named view,
while in a spreadsheet application, for example, a sublocation might be a cell or group of cells.
The display string is usually the same as the hyperlink's description. If the description is null, the
hyperlink's name and sublocation are used instead, in name sublocation format.
Hyperlinks may also have nesting levels. Nesting level is only of interest when dealing with
hyperlink collections associated with an entity within a block, or with collections associated with an
INSERT entity.
AcDbHyperlinkCollection Class
This class is a collection of AcDbHyper l i nk objects, and has a variety of methods for adding and
removing those objects. The AcDbHyper l i nkCol l ect i on deletes its contents when they are
removed, and when the collection object itself is deleted. Hyperlinks in the collection are
numbered from zero.
AcDbEntityHyperlinkPE Class
The methods of the AcDbEnt i t yHyper l i nkPE class allow you to set, get, and count the hyperlinks
associated with an entity.
The following function lists the hyperlinks associated with an entity and allows new hyperlinks to be
added in their place. (Error checking is not shown.)
Hyperlink Class Overview
Hyperlink Example
Page 104 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
voi d AddHyper l i nk( )
{
ads_name en;
ads_poi nt pt ;
AcDbEnt i t y * pEnt ;
AcDbObj ect I d pEnt I d;
/ / Pr ompt user t o sel ect ent i t y.
acedEnt Sel ( " \ nSel ect an Ent i t y: " , en, pt ) ;
/ / Get Obj ect i d.
acdbGet Obj ect I d( pEnt I d, en) ;
/ / Open obj ect f or wr i t e.
acdbOpenObj ect ( pEnt , pEnt I d, AcDb: : kFor Wr i t e) ;
/ / The hyper l i nk col l ect i on obj ect i s cr eat ed i nsi de
/ / of get Hyper l i nkCol l ect i on bel ow.
/ / I t i s our r esponsi bi l i t y t o del et e i t .
AcDbHyper l i nkCol l ect i on * pcHCL = NULL;
/ / Get t he hyper l i nk col l ect i on associ at ed wi t h t he ent i t y.
ACRX_X_CALL( pEnt , AcDbEnt i t yHyper l i nkPE) - >
get Hyper l i nkCol l ect i on( pEnt , pcHCL, f al se, t r ue) ;
/ / I f a hyper l i nk exi st s al r eady, say so.
i f ( pcHCL- >count ( ) ! = 0)
{
AcDbHyper l i nk * pcHO;
acut Pr i nt f ( " \ nThe f ol l owi ng hyper l i nk i nf o al r eady exi st s
on t hi s ent i t y: " ) ;
/ / I t er at e t hr ough col l ect i on and pr i nt exi st i ng hyper l i nks.
i nt i = 0;
f or ( i = 0; i < pcHCL- >count ( ) ; i ++)
{
/ / Get poi nt t o cur r ent hyper l i nk obj ect .
pcHO = pcHCL- >i t em( i ) ;
acut Pr i nt f ( " \ nHyper l i nk name: %s" , pcHO- >name( ) ) ;
acut Pr i nt f ( " \ nHyper l i nk l ocat i on: %s" ,
pcHO- >subLocat i on( ) ) ;
acut Pr i nt f ( " \ nHyper l i nk descr i pt i on: %s" ,
pcHO- >descr i pt i on( ) ) ;
}
acut Pr i nt f ( " \ n** Al l wi l l be r epl aced. **" ) ;
/ / Remove exi st i ng hyper l i nks f r omcol l ect i on.
/ / RemoveAt wi l l del et e obj ect s t oo.
f or ( i = pcHCL- >count ( ) - 1; i >= 0; i - - )
{
pcHCL- >r emoveAt ( i ) ;
}
}
/ / Get new hyper l i nks f or t hi s ent i t y.
f or ( ; ; )
{
acut Pr i nt f ( " \ nEnt er nul l name, l ocat i on, and descr i pt i on t o
t er mi nat e i nput r equest s. " ) ;
/ / Pr ompt user f or name and descr i pt i on.
char sName[ 100] , sLocat i on[ 100] , sDescr i pt i on[ 100] ;
i f ( acedGet St r i ng( TRUE, " \ nEnt er hyper l i nk name: " , sName)
! = RTNORM)
acut Pr i nt f ( " I nval i d i nput \ n" ) ;
i f ( acedGet St r i ng( TRUE, " \ nEnt er hyper l i nk l ocat i on: " ,
sLocat i on) ! = RTNORM)
acut Pr i nt f ( " I nval i d i nput \ n" ) ;
i f ( acedGet St r i ng( TRUE, " \ nEnt er hyper l i nk descr i pt i on: " ,
sDescr i pt i on) ! = RTNORM)
acut Pr i nt f ( " I nval i d i nput \ n" ) ;
/ / Add hyper l i nk or exi t pr ompt i ng.
i f ( st r cmp( sName, " " ) | | st r cmp( sLocat i on, " " ) | |
st r cmp( sDescr i pt i on, " " ) )
pcHCL- >addTai l ( sName, sDescr i pt i on, sLocat i on) ;
el se
br eak;
}
/ / Add t hese hyper l i nks t o t he sel ect ed ent i t y ( opened above) .
ACRX_X_CALL( pEnt , AcDbEnt i t yHyper l i nkPE) - >
set Hyper l i nkCol l ect i on( pEnt , pcHCL) ;
/ / Del et e t he col l ect i on. The col l ect i on wi l l del et e al l i t s
Page 105 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
This section describes the container objects used in AutoCAD
programmers. An xrecord is an
instance of class AcDbxr ecor d, which is a subclass of AcDbObj ect . Xrecord state is defined as the
contents of a resbuf chain, which is a list of data groups, each of which in turn contains a DXF group
code plus associated data. The value of the group code defines the associated data type. Group codes
for xrecords are in the range of 1 through 369. The following section describes the available DXF group
codes.
There is no inherent size limit to the amount of data you can store in an xrecord. Xrecords can be
owned by any other object, including the extension dictionary of any object, the named object
dictionary, any other dictionary, or other xrecords.
No notification is sent when an xrecord is modified. If an application needs to know when an object
owning an xrecord has been modified, the application will need to send its own notification.
The AcDbXr ecor d class provides two member functions for setting and obtaining resbuf chains, the
set f r omRbChai n( ) and r bChai n( ) functions:
The AcDbXr ecor d: : set Fr omRbChai n( ) function replaces the existing resbuf chain with the chain passed
in.
Topics in this section
DXF Group Codes for Xrecords
Xrecord Examples
The following table lists the DXF group codes that can be used in xrecords.
Xrecords
Acad: : Er r or St at us
AcDbXr ecor d: : set Fr omRbChai n(
const r esbuf & pRb,
AcDbDat abase* auxDb = NULL) ;
Acad: : Er r or St at us
AcDbXr ecor d: : r bChai n(
r esbuf ** ppRb,
AcDbDat abase* auxDb = NULL) const ;
DXF Group Codes for Xrecords
DXF group
code ranges
for xrecords
From To Data Type
1 4 Text
6 9 Text
10 17 Point or vector (3 reals)
Page 120 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
For a description of hard and soft owners and pointers, see Deriving from AcDbObject.
The following ObjectARX examples consist of two functions: cr eat eXr ecor d( ) and l i st Xr ecor d( ) . The
first function adds a new xrecord to a dictionary, adds the dictionary to the named object dictionary,
and then adds data to the xrecord. The l i st Xr ecor d( ) function opens an xrecord, obtains its data list,
and sends the list to be printed. For the complete program, see the ObjectARX
samples\database\xrecord_dg directory.
38 59 Real
60 79 16-bit integer
90 99 32-bit integer
102 102 Control string { or }
140 149 real
160 169 64-bit integer
170 179 16-bit integer
210 219 Real
270 279 16-bit integer
280 289 8-bit integer
300 309 Text
310 319 Binary chunk
320 329 Handle
330 339 Soft pointer ID
340 349 Hard pointer ID
350 359 Soft ownership ID
360 369 Hard ownership ID
Xrecord Examples
Page 121 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
voi d
cr eat eXr ecor d( )
{
AcDbDi ct i onar y *pNamedobj , *pDi ct ;
acdbHost Appl i cat i onSer vi ces( ) - >wor ki ngDat abase( )
- >get NamedObj ect sDi ct i onar y( pNamedobj , AcDb: : kFor Wr i t e) ;
/ / Check t o see i f t he di ct i onar y we want t o cr eat e i s
/ / al r eady pr esent . I f not , t hen cr eat e i t and add
/ / i t t o t he named obj ect di ct i onar y.
/ /
i f ( pNamedobj - >get At ( " ASDK_DI CT" , ( AcDbObj ect *&) pDi ct ,
AcDb: : kFor Wr i t e) == Acad: : eKeyNot Found)
{
pDi ct = new AcDbDi ct i onar y;
AcDbObj ect I d Di ct I d;
pNamedobj - >set At ( " ASDK_DI CT" , pDi ct , Di ct I d) ;
}
pNamedobj - >cl ose( ) ;
/ / Add a new xr ecor d t o t he ASDK_DI CT di ct i onar y.
/ /
AcDbXr ecor d *pXr ec = new AcDbXr ecor d;
AcDbObj ect I d xr ecObj I d;
pDi ct - >set At ( " XREC1" , pXr ec, xr ecObj I d) ;
pDi ct - >cl ose( ) ;
/ / Cr eat e a r esbuf l i st t o add t o t he xr ecor d.
/ /
st r uct r esbuf *pHead;
ads_poi nt t est pt = {1. 0, 2. 0, 0. 0};
pHead = acut Bui l dLi st ( AcDb: : kDxf Text ,
" Thi s i s a t est Xr ecor d l i st " ,
AcDb: : kDxf XCoor d, t est pt ,
AcDb: : kDxf Real , 3. 14159,
AcDb: : kDxf Angl e, 3. 14159,
AcDb: : kDxf Col or , 1,
AcDb: : kDxf I nt 16, 180,
0) ;
/ / Add t he dat a l i st t o t he xr ecor d. Not i ce t hat t hi s
/ / member f unct i on t akes a r ef er ence t o r esbuf , NOT a
/ / poi nt er t o r esbuf , so you must der ef er ence t he
/ / poi nt er bef or e sendi ng i t .
/ /
pXr ec- >set Fr omRbChai n( *pHead) ;
acut Rel Rb( pHead) ;
pXr ec- >cl ose( ) ;
}
/ / Get s t he xr ecor d associ at ed wi t h t he key XREC1 and
/ / l i st s out i t s cont ent s by passi ng t he r esbuf l i st t o t he
/ / f unct i on pr i nt Li st .
/ /
voi d
l i st Xr ecor d( )
{
AcDbDi ct i onar y *pNamedobj ;
acdbHost Appl i cat i onSer vi ces( ) - >wor ki ngDat abase( )
- >get NamedObj ect sDi ct i onar y( pNamedobj , AcDb: : kFor Read) ;
/ / Get t he di ct i onar y obj ect associ at ed wi t h t he key ASDK_DI CT.
/ /
AcDbDi ct i onar y *pDi ct ;
pNamedobj - >get At ( " ASDK_DI CT" , ( AcDbObj ect *&) pDi ct ,
AcDb: : kFor Read) ;
pNamedobj - >cl ose( ) ;
/ / Get t he xr ecor d associ at ed wi t h t he key XREC1.
/ /
AcDbXr ecor d *pXr ec;
pDi ct - >get At ( " XREC1" , ( AcDbObj ect *&) pXr ec,
AcDb: : kFor Read) ;
pDi ct - >cl ose( ) ;
st r uct r esbuf *pRbLi st ;
pXr ec- >r bChai n( &pRbLi st ) ;
pXr ec- >cl ose( ) ;
pr i nt Li st ( pRbLi st ) ;
acut Rel Rb( pRbLi st ) ;
Page 122 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Page 123 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm