You are on page 1of 123

Topics in this section

ObjectARX Introductory Concepts


Topics in this section
Overview of ObjectARX
Database Primer
ObjectARX Application Basics
Database Operations
Database Objects
Entities
Container Objects
ObjectARX, the AutoCADRuntime Extension programming environment, includes C++ libraries that
are the building blocks you can use to develop AutoCAD applications, extend AutoCAD classes and
protocol, and create new commands that operate in the same manner as built-in AutoCAD commands.
You can add new classes and export them for use by other programs. You can also extend the
ObjectARX protocol by adding functions at runtime to existing AutoCAD classes.
ObjectDBX

is the foundation for ObjectARX and for the RealDWG



SDK.
This section defines those terms, provides an overview of some important groups of ObjectARX and
ObjectDBX classes, and gives information for getting started with ObjectARX. The ObjectARX
Developer's Guide assumes that you are familiar with C++, object-oriented programming, and
AutoCAD.
Topics in this section
The ObjectARX Programming Environment
The ObjectARX Documentation Set
ObjectARX Class Groups
Getting Started
The ObjectARX programming environment provides an object-oriented C++ application programming
interface for developers to use, customize, and extend AutoCAD. An ObjectARX application is a
dynamic link library (DLL) that shares the address space of AutoCAD and makes direct function calls to
AutoCAD.
The ObjectARX libraries comprise a versatile set of tools for application developers to take advantage of
ObjectARX Introductory Concepts
ObjectARX Introductory Concepts
Overview of ObjectARX
The ObjectARX Programming Environment
Page 1 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
AutoCAD's open architecture, providing direct access to AutoCAD database structures, the graphics
system, and native command definition. In addition, these libraries are designed to work in conjunction
with .NET, ActiveX Automation, COM, and Visual LISP so that developers can choose the programming
tools best suited to their needs and experience.
The following terms describe technologies that are closely related to ObjectARX:
ObjectDBX

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

concepts, and provides step-by-


step procedures and code examples.
ObjectARX Reference. Documents the ObjectARX and ObjectDBX classes, member functions, global
functions, namespaces, enumerations, structures, and macros.
AutoCAD Managed Class Reference. Documents the Autodesk.AutoCAD managed classes.
ObjectARX Application Interoperability Guidelines. Provides a checklist of items to consider in order
to ensure that your application interacts appropriately with AutoCAD

and other applications.


ObjectARX Readme. Describes last-minute changes and additions to ObjectARX.
Topics in this section
Using the ObjectARX Developer's Guide
The ObjectARX Developer's Guideis organized in seven parts:
Part I: Describes the fundamental concepts of ObjectARX.
Part II: Shows how to work with ObjectARX global functions and MFC to create and interact with user
interfaces.
Part III: Describes how to create custom classes in ObjectARX.
Part IV: Examines topics of interest to more advanced users, such as proxy objects, notification, and
protocol extension.
Part V: Describes how to develop managed (.NET) applications that work with AutoCAD.
Part VI: Describes how to work with external programming environments such as COM and ActiveX
Automation.
Part VII: Describes the ObjectARX graphics interface, geometry, visualization, and boundary
representation libraries.
The ObjectARX Documentation Set
Using the ObjectARX Developer's Guide
ObjectARX Class Groups
Page 4 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
The following groups of classes and functions form the basis of the ObjectARX environment:
AcRx
Classes for binding an application and for runtime class registration and identification.
AcEd
Classes for registering native AutoCAD commands and for AutoCAD event notification.
AcDb
AutoCAD database classes.
AcGi
Graphics classes for rendering AutoCAD entities.
AcGe
Utility classes for common linear algebra and geometric objects.
The following table lists the libraries required to link ObjectARX applications. All ObjectARX applications
must link with acad.lib and rxapi.lib. Other libraries may also be required, depending on the prefix of the
ObjectARX classes and functions that you are using.
Required ObjectARX libraries
The following sections take a closer look at these major groups of ObjectARX classes. In addition to
these groups, numerous extensions exist that define their own prefixes. These extensions are discussed
in later chapters, or in the ObjectARX Reference.
For the ObjectARX class hierarchy diagram, see classmap.dwg in the ObjectARX classmap subdirectory.
For more information about specific classes and member functions, see the ObjectARX Reference.
Topics in this section
AcRx Classes
AcEd Classes
AcDb Classes
AcGi Classes
AcGe Classes
The ObjectARX classes with an AcRx prefix provide system-level functionality such as DLL initialization
and linking and runtime class registration and identification. The AcRxObj ect base class provides the
following facilities:
Object runtime class identification and inheritance analysis
Prefix Required Libraries
AcRx rxapi.lib, acdb20.lib
AcEd acad.lib, rxapi.lib, acdb20.lib
AcDb rxapi.lib, acdb20.lib
AcGi acgiapi.lib, rxapi.lib, acdb20.lib
AcGe rxapi.lib, acge20.lib, acdb20.lib
AcRx Classes
Page 5 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Runtime addition of new protocol to an existing class (see Protocol Extension)
Object equality and comparison testing
Object copy
The AcRx library also provides a set of C++ macros to help you create new ObjectARX classes derived
from AcRxObj ect (see Deriving a Custom ObjectARX Class).
Every subclass of AcRxObj ect has an associated class descriptor object (of type AcRxCl ass) that is used
for runtime type identification. ObjectARX provides functions for testing whether an object is of a
particular class or derived class, functions for determining whether two objects are of the same class,
and functions for returning the class descriptor object for a given class.
AcRxDi ct i onar y is another important class in this group. A dictionary is a mapping from a text string to
another object. ObjectARX places its objects, classes, and service dictionaries in a global object
dictionary, which is an instance of the AcRxDi ct i onar y class. Applications can add objects to this
dictionary so that they are accessible to other applications.
For more information on using AcRx classes, see ObjectARX Application Basics,, Deriving a Custom
ObjectARX Class, and Protocol Extension.
The ObjectARX classes with an AcEd prefix include classes for defining and registering new AutoCAD
commands that operate in the same manner as built-in AutoCAD commands. The new commands you
define are referred to as "native" commands because they reside in the same internal structure (the
AcEdCommandSt ack) as built-in commands. The AcEd classes also include AcEdi t or React or , which
monitors the state of the AutoCAD editor and notifies the application when specified events occur, such
as starting, ending, or canceling a command. Global functions with the AcEd prefix allow applications to
interact with AutoCAD.
For information on registering new AutoCAD commands using ObjectARX, see ObjectARX Application
Basics. For an example of using an editor reactor, see Notification.
The ObjectARX classes with an AcDb prefix are components of the AutoCAD database. This database
stores all the information for the graphical objects, called entities, that compose an AutoCAD drawing,
as well as the nongraphical objects (for example, layers, linetypes, and text styles) that are also part of
a drawing. You can query and manipulate existing instances of AutoCAD entities and objects with the
AcDb classes and functions, and you can create new instances of database objects.
The AutoCAD database contains these major elements:
A set of nine symbol tables that own uniquely named symbol table entry objects. These objects
represent various commonly used AcDbDat abase objects and data members.
A named object dictionary (of class AcDbDi ct i onar y), which provides the "table of contents" for an
AutoCAD drawing. Initially, this table of contents contains the IDs of the four other dictionaries used
by AutoCAD. Applications you develop are free to add other objects to the dictionary.
A fixed set of about 200 header variables, whose values are set by AutoCAD.
For more information about the AcDb classes, see Database Primer,, Database Operations,, Database
Objects,, Entities,, and Container Objects. For information on deriving new classes from AcDbObj ect and
AcDbEnt i t y, see Deriving from AcDbObject and Deriving from AcDbEntity.
AcEd Classes
AcDb Classes
Page 6 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
The ObjectARX classes with an AcGi prefix relate to the graphics interface used for drawing AutoCAD
entities. These classes are used by the AcDbEnt i t y member functions wor l dDr aw( ) , vi ewpor t Dr aw( ) ,
and saveAs( ) , which are all part of the standard entity protocol. The subWor l dDr aw( ) function, which is
called by wor l dDr aw( ) to provide the draw behavior specific to the custom entity, must be overriden by
all custom entity classes. The AcGi Wor l dDr aw object provides an API through which
AcDbEnt i t y: : wor l dDr aw( ) can produce its graphical representation in all viewports simultaneously.
Similarly, the AcGi Vi ewpor t Dr aw object provides an API through which the AcDbEnt i t y: : vi ewpor t Dr aw
( ) function can produce different graphical representations for each viewport.
For more information on using AcGi classes, see Deriving from AcDbEntity and The Graphics Interface
Library.
The ObjectARX classes with an AcGe prefix are used by the AcDb library to perform common 2D and 3D
geometric operations. AcGe includes utility classes such as vectors and matrices and basic geometric
objects such as points, curves, and surfaces.
The AcGe classes can be grouped into two major subsets: classes for 2D geometry and classes for 3D
geometry. The major abstract base classes are AcGeEnt i t y2d and AcGeEnt i t y3d. Several basic classes
not derived from any other class include AcGePoi nt 2d, AcGeVect or 2d, and AcGeMat r i x2d. These basic
classes can be used to perform many types of common operations, such as adding a vector to a point,
computing the dot or cross product of two vectors, and computing the product of two matrices. The
higher-level classes in this group are implemented using these basic classes.
The AcGe classes provide several different coordinate systems. For more information, see Using the
Geometry Library. The sample programs in this documentation illustrate numerous common uses of
AcGe classes.
ObjectARX is posted on the Web as a self-extracting ZIP file. To install ObjectARX, download and
double-click on the ZIP file.
The following topics discuss the system requirements for ObjectARX development, the directory
structure of the SDK, and the basics of creating and debugging an ObjectARX application using Microsoft
Visual Studio.
Topics in this section
Software Development Environment and System Requirements
ObjectARX Directory Tree
Setting up an ObjectARX Project Using Microsoft Visual Studio
Compile and Debug Mixed-mode Projects
Developing applications with ObjectARX 2015 on 32-bit requires the following software and hardware:
AcGi Classes
AcGe Classes
Getting Started
Software Development Environment and System Requirements
Page 7 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Microsoft Windows 7 ( Enterprise, Professional, or Ultimate edition) and Windows 8/8.1
( Enterprise or Pro edition)
Intel Pentium 4 or AMD Athlon Dual Core, 3.0 GHz or Higher with SSE2 technology
4 GB RAM (8 GB recommended)
Developing applications with ObjectARX 2015 on 64-bit requires the following software and hardware:
Microsoft Windows 7 ( Enterprise, Professional, or Ultimate edition) and Windows 8/8.1 (64-
bit, Enterprise or Pro edition)
AMD Athlon with SSE2 technology or AMD Opteron with SSE2 technology or Intel Xeon with Intel
EM64T support with SSE2 technology or Intel Pentium 4 with Intel EM64T support with SSE2
technology
4 GB RAM (8 GB recommended)
Common requirements for all systems:
500 MB free disk space for installation
1,024x768 VGA with True Color
Microsoft Internet Explorer 9.0 Internet browser, available as dow nload only
Microsoft Visual Studio 2012 Update 4
Note
Windows XP Home, Windows Vista Home Premium, or Windows Vista Home Basic are not supported
development platforms.
The complete ZIP file for ObjectARX creates the subdirectories described here. Several subsets of the
SDK are also available for download, so your ObjectARX directory may not contain all of these
subdirectories.
classmap
The classmap directory contains an AutoCAD drawing illustrating the ObjectARX class hierarchy.
docs
The docs directory contains the ObjectARX online help files. The main file is arxdoc.chm, which
includes all the other help files.
inc
The inc directory contains the common ObjectARX header files.
inc-win32
The inc-win32 directory contains the ObjectARX header files for 32-bit operating systems.
inc-x64
The inc-x64 directory contains the ObjectARX header files for 64-bit operating systems.
lib-win32
The lib-win32 directory contains the ObjectARX library files for 32-bit operating systems.
lib-x64
The lib-x64 directory contains the ObjectARX library files for 64-bit operating systems.
Redistrib
ObjectARX Directory Tree
Page 8 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
The Redistrib directory contains a set of DLLs, some of which may be required for an ObjectARX
application to run. Developers should copy the DLLs that they need for application development to
a directory in the AutoCAD search path, and package the necessary DLLs with their ObjectARX
applications for distribution. Redistrib-win32 is for 32-bit operating systems, while Redistrib-x64 is
for 64-bit operating systems.
samples
The samples directory contains examples of ObjectARX applications. Samples are grouped into
subdirectories according to their programmatic focus. A summary Readme file is provided in the
root directory in addition to the Readme files in the individual sample subdirectories. The most
significant set of sample ObjectARX applications is in the polysamp subdirectory.
utils
The utils directory contains subdirectories for applications that are extensions to ObjectARX,
including brep for boundary representation and ObjARXWiz for the ObjectARX wizards.
The first step in building an ObjectARX application is to set up a project in Microsoft Visual Studio. This
section lists the project settings and minimum files required to build a basic ObjectARX application.
Alternatively, you can create a new ObjectARX project using the ObjectARX Wizards for AutoCAD.
Note The ObjectARX Wizards have been removed from the ObjectARX SDK. You can find the latest
version at the AutoCAD Developer Center.
Use the following settings for your project
Set the application type to DLL.
Specify the ObjectARX library and include file locations.
The easiest way to do this is to add the ObjectARX include and library directories to your MSVC++
environment settings (in the Microsoft Visual Studio menu under Tools Options Projects and
Solutions VC++ Directories). You can also specify the locations in the Project Properties, but you'll
need to include full paths to the files for every project you create.
For all configurations (debug and release), set the runtime library for linking to Multithreaded DLL (in
your projects Property Pages C/C++ Code
Generation Runtime Library).
For all configurations (debug and release), set the Detect 64-bit Portability Issues option to No (in
your projects Property Pages underConfiguration Properties C/C++ General Detect 64-
bit Portability Issues). This setting suppresses compiler warning 4311 for pointer assignments that
are not 64-bit compatible. Some ObjectARX header files contain such assignments.
If you prefer, you can control this warning instead by using #pr agma war ni ng statements. See the
Microsoft documentation for more information about #pr agma war ni ng statements.
Set the output file name (in your projects Property Pages under Configuration Properties Linker
General Output File) to a name with an .arx extension. If you include a DEF file with a LIBRARY
statement in your project, this name should match the LIBRARY value.
Note
LIBRARY statements are optional in DEF files.
Add the ObjectARX libraries necessary for your program (in your projects Property Pages under
Configuration Properties Input Additional Dependencies).
For example, the minimum code shown below requires rxapi.lib and acdb19.lib.
You will need to add source file(s) to the new project. If you already have source files or are using
sample program source files, add these files.
Setting up an ObjectARX Project Using Microsoft Visual Studio
Page 9 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
This example shows the minimum code needed to make an ObjectARX program.
Add a new C++ source file to the project and enter the following code:
The project also needs a definition file. Add a new text file to the project and name it with a .def
extension.
Enter the following code in the DEF file
The EXPORTS section should be present and must contain at least the acr xEnt r yPoi nt function (unless
you have used another mechanism to export this function, like the Windows _decl spec( dl l expor t )
convention).
Using PRIVATE in the DEF file prevents these symbols from appearing in an import library for this
ObjectARX application. The symbol will still appear in the application's export table, allowing AutoCAD to
find and call the symbol. This is important because every ObjectARX application or Object Enabler must
have its own implementation of these functions. The application gets the implementation of
acr xGet Api Ver si on by virtue of linking to the static library rxapi.lib. If ObjectARX application app2 uses
symbols from ObjectARX application app1 by linking to app1.lib, it would be an error for app2 to get its
definition of acr xGet Api Ver si on from the app1 import library. Using PRIVATE in the DEF file will
prevent this. Making certain to link to rxapi.lib prior to linking to any import library for another
ObjectARX application will also prevent this.
The LIBRARY name should match the file name of the ObjectARX file you are going to create and must
show an .arx extension. For example, if your desired output file name is test.arx, the LIBRARY
statement in your DEF file should show the full name test.arx.
Note If you wish, you can include the standard ObjectARX DEF file, AcRxDefault.def, in your project.
This file defines the required ObjectARX exports properly and is found in the \inc SDK directory. It does
not use a LIBRARY statement.
#i ncl ude " r xr egsvc. h"
#i ncl ude " acut ads. h"
/ / Si mpl e acr xEnt r yPoi nt code. Nor mal l y i nt i al i zat i on and cl eanup
/ / ( such as r egi st er i ng and r emovi ng commands) shoul d be done her e.
/ /
ext er n " C" AcRx: : AppRet Code
acr xEnt r yPoi nt ( AcRx: : AppMsgCode msg, voi d* appI d)
{
swi t ch( msg) {
case AcRx: : kI ni t AppMsg:
/ / Al l ow appl i cat i on t o be unl oaded
/ / Wi t hout t hi s st at ement , Aut oCAD wi l l
/ / not al l ow t he appl i cat i on t o be unl oaded
/ / except on Aut oCAD exi t .
/ /
acr xUnl ockAppl i cat i on( appI d) ;
/ / Regi st er appl i cat i on as MDI awar e.
/ / Wi t hout t hi s st at ement , Aut oCAD wi l l
/ / swi t ch t o SDI mode when l oadi ng t he
/ / appl i cat i on.
/ /
acr xRegi st er AppMDI Awar e( appI d) ;
acut Pr i nt f ( " \ nExampl e Appl i cat i on Loaded" ) ;
br eak;
case AcRx: : kUnl oadAppMsg:
acut Pr i nt f ( " \ nExampl e Appl i cat i on Unl oaded" ) ;
br eak;
}
r et ur n AcRx: : kRet OK;
}
LI BRARY " obj ect ar x_pr ogr am_name. ar x"
EXPORTS
acr xEnt r yPoi nt PRI VATE
acr xGet Api Ver si on PRI VATE
Page 10 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Once you have added these two source files, you can build a basic ObjectARX application.
To test the application, start AutoCAD and load the program using one of the following
methods
Use the AutoLISP function (arxload "program_name") .
Use the ARX command.
Use the APPLOAD command, which opens a dialog allowing you to maintain a list of applications to
load/unload.
For more information, see Loading an ObjectARX Application.
You can use Microsoft Visual Studio 2012 Update 4 to compile ObjectARX applications for use in
AutoCAD 2015. For AutoCAD 2014 and AutoCAD 2013, you can use Microsoft Visual Studio 2010doing
this allows you to maintain one project, one development environment, and one version of your
application.
Note
This topic is important to those that need to support applications for AutoCAD 2014 and AutoCAD 2013.
AutoCAD 2015 targets the .NET Framework 4.5, which is the default target for new projects in Microsoft
Visual Studio 2012 Update 4. No additional steps are required to test or debug an application in
AutoCAD 2015.
To use Microsoft Visual Studio 2010 to build and debug projects in AutoCAD 2011 or AutoCAD 2012, you
need to change the target .NET Framework and Platform Toolset for your projects. Targeting a
different .NET Framework with Microsoft Visual Studio 2010 requires you to install:
Microsoft Visual Studio 2008 with Service Pack 1
.NET Framework 3.5
The following explains how to change the target .NET Framework and Platform Toolset for a Microsoft
Visual Studio 2010 project:
1. Migrate your Microsoft Visual Studio 2008 project or create a new project in Microsoft Visual Studio
2010.
2. In Microsoft Visual Studio, click Project menu Properties.
3. In the Property Pages dialog box, Configuration drop-down list, choose a configuration to edit.
4. In the Properties tree, on the left, expand Configuration Properties and select General.
5. In the Properties pane, on the right, under the General category select Platform Toolset and choose
v90. Click OK.
6. Next, close the solution/project in Microsoft Visual Studio. Click File menu Close Solution.
7. In Windows Explorer, browse to the location of your project.
8. Locate the file with the extension .vcsproj.
For example, the file would be named AdskCustomPalette.vcsproj if the project name was
AdskCustomPalette. The project name might not be the same as the solution.
9. Right-click the file with the extension .vcsproj. Click Open with Notepad.
If needed, hold Shift and then right-click. Click Open With and then Choose Program. In the Open
With dialog box, select Notepad and click OK.
Compile and Debug Mixed-mode Projects
Page 11 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
10. Locate the PropertyGroup element.
11. Change the value of v4.0 for the TargetFrameworkVersion attribute to v3.5. The attribute should
now look like <Tar get Fr amewor kVer si on>v3. 5</ Tar get Fr amewor kVer si on>.
Note If you need to use .NET Framework 3.5 Client or .NET Framework 4.0 Client, add
<Tar get Fr amewor kPr of i l e>Cl i ent </ Tar get Fr amewor kPr of i l e> to the PropertyGroup element.
12. In Notepad, click File menu > Save. Close Notepad.
13. Reopen the project in Microsoft Visual Studio.
14. Build/debug the project as you would with Microsoft Visual Studio.
Note
You should not have to change the TargetFrameworkVersion attribute back to v4.0 when you want to
debug an application in AutoCAD 2014 from Microsoft Visual Studio 2010. For AutoCAD 2015, you have
to use Microsoft Visual Studio 2012 and .NET version should be 4.5.
Additional information on multi-target projects can be found at the following URLs:
http://blogs.msdn.com/b/vcblog/archive/2009/12/08/c-native-multi-targeting.aspx
http://blogs.msdn.com/b/vcblog/archive/2010/03/02/visual-studio-2010-c-project-upgrade-
guide.aspx
The AutoCAD

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

file can be loaded.


This section describes creating a line, circle, layer, and group in AutoCAD and shows how AutoCAD adds
these objects to the database. First, suppose the user creates a line in model space with the following
command:
line 4,2 10,7
In the database, AutoCAD creates an instance of class AcDbLi ne and then stores it in the model space
block table record as shown in the following illustration:
Essential Database Objects
Creating Objects in AutoCAD
Page 14 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
When you first invoke AutoCAD and the database is in its default state, entities are added to model
space, the main space in AutoCAD, which is used for model geometry and graphics. Paper space is
intended to support documentation geometry and graphics, such as drafting sheet outlines, title
blocks, and annotational text. The entity creation commands in AutoCAD (LINE, in this case) cause the
entity to be added to the current database as well as to the model space block. You can ask any entity
which database and which block it belongs to.
Next, suppose the user creates a circle with this command:
circle 9,3 2
Again, AutoCAD creates an instance of the appropriate entityhere, AcDbCi r cl eand adds it to the
model space block table record.
Next, the user creates a layer:
layer _ make mylayer
AutoCAD creates a new layer table record to hold the layer and then adds it to the layer table.
Finally, the user groups all the entities together:
group 3,2 9,3
AutoCAD creates a new group object and adds it to the GROUP dictionary, which is contained in the
named object dictionary. The new group contains a list of the object IDs of the objects that compose the
group.
Page 15 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
The sample ObjectARX

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

application. It lists the messages passed by


AutoCAD

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

function with acedDef un


( )
Messages that are sent to applications that have registered a service with ObjectARX
Messages only responded to by applications that use ActiveX Automation
The following five tables describe the messages that AutoCAD sends to ObjectARX applications. The first
table lists messages sent to all applications.
Messages sent to all applications
The next table lists messages that AutoCAD sends to applications that have registered an AutoLISP
Creating Custom Classes
Responding to AutoCAD Messages
Message Description
kInitAppMsg Sent when the ObjectARX application is loaded to open
communications between AutoCAD and the application.
kUnloadAppMsg Sent when the ObjectARX application is unloaded (either when the
user unloads the application or when AutoCAD itself is terminated).
Closes files and performs cleanup operations.
kLoadDwgMsg Sent once when the drawing is opened. Then, if the application
registers any functions with AutoLISP, AutoCAD sends this message
once for each drawing loaded into the editor. The AutoCAD editor is
fully initialized at this point, and all global functions are available.
However, you cannot use an acedCommand() function from a
kLoadDwgMsg.
kSaveMsg Sent when AutoCAD is saving the drawing because a SAVE, SAVEAS,
NEW, or OPEN command is entered.
kUnloadDwgMsg Sent (in the reverse order of load time) when the user quits a drawing
session.
kPreQuitMsg Sent when AutoCAD quits, but before it begins to unload all ObjectARX
applications.
Page 20 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
function with acedDef un( ) :
Messages sent only if the application has registered an AutoLISP function
The next table lists the messages that an application receives if it has registered a service with
ObjectARX.
Messages only received by applications that have registered a service
The next table lists the messages that an application needs to respond to if it is using ActiveX
Automation. See COM and ActiveX Automation
Messages only responded to by applications that use ActiveX Automation
See the rxdefs.h file where these enumeration constants are defined by the AppMsgCode type
declaration.
You will need to decide which messages your ObjectARX application will respond to. The following table
describes recommended actions upon receipt of a given message.
ObjectARX application reactions to AutoCAD messages
Message Description
kInvkSubrMsg Sent to invoke functions registered using acedDefun().
kEndMsg Sent only when the END command is entered and there are changes
that need to be saved (when dbmod != 0). kEndMsg is not sent for a
NEW or OPEN, instead, kSaveMsg and kLoadDwgMsg are sent. For
END, if dbmod = 0, then kQuitMsg is sent instead of kEndMsg.
kQuitMsg Sent when AutoCAD quits (ends without saving) the drawing because
a QUIT command was entered. The kQuitMsg can also be received
with the END command, as noted above. If the END command is sent
and dbmod = 0, then kQuitMsg is sent.
Note: kQuitMsg can be sent before kPreQuitMsg.
kCfgMsg Sent when AutoCAD returns from the configuration program, and used
only for a change to the display driver.
Message Description
kDependencyMsg Sent when the ObjectARX application has registered an AcRxService
object and the dependency count on that service changes from 0 to 1.
kNoDependencyMsg Sent when the ObjectARX application has registered an AcRxService
object and the dependency count on that service changes from 1 to 0.
Message Description
kOleUnloadAppMsg Sent to determine if the application can be unloaded (that is, none of
its ActiveX objects or interfaces are being referenced by other
applications).
Message Recommended Actions
kInitAppMsg Do register services, classes, AcEd commands and reactors, and
Page 21 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
AcRxDynamicLinker reactors. Initialize application's system resources,
such as devices and windows. Perform all one-time early initialization.
AcRx, AcEd, and AcGe are all active. Store the value of the pkt
parameter if you want to unlock and relock your application.
Don't expect device drivers to be initialized, any user interface resources
to be active, applications to be loaded in a particular order, AutoLISP to
be present, or any databases to be open. Calls involving any of these
assumptions will result in an error condition, sometimes fatal. AcDb and
AcGi libraries are generally not yet active, although related AcRx and
other structures are in place.
kUnloadAppMsg Do perform final system resource cleanup. Anything started or created
in kInitAppMsg should now be stopped or destroyed.
Don't expect things to be any different from the description of
kInitAppMsg. AutoCAD could be mostly dismantled by the time this call
is made, except for the libraries listed as active in the kInitAppMsg Do
description.
kOleUnloadAppMsg This message should be responded to only by applications using ActiveX
Automation.
Do respond with AcRx::kRetOK, if the application can be unloaded (none
of its ActiveX objects or interfaces are being referenced by other
applications). If it cannot be unloaded, respond with AcRx::kRetError.
kLoadDwgMsg Do perform initialization relevant to the current drawing edit session.
AcDb, AcGi, and the user interface API are all now active. Whether
anything has been done to the drawing is not specified. All AutoCAD-
supplied APIs are now active. You can perform AutoLISP function
registration at this time, and initialize the user interface. Other
operations to perform now include polling AutoCAD drivers and querying
AcEditorReactor events if you want the earliest possible access to
acdbHostApplicationServices()->workingDatabase().
Don't do anything you would not want to happen for every drawing edit
session. Assume this message is sent more than once per program
execution.
kUnloadDwgMsg Do release or clean up everything started or registered in response to
kLoadDwgMsg code. Release all AcDb reactors, excluding persistent
reactors.
Don't release system resources that are not tied to an edit session, or
clean up AcRx classes, AcEd reactors, or commands; they remain valid
across edit sessions.
kDependencyMsg Do perform any actions that are necessary for your application when
other applications become dependent on it, such as locking your
application so that it cannot be unloaded.
kNoDependencyMsg Do perform any actions that are necessary for your application when
there are no longer any other applications dependent on yours, such as
unlocking your application so that it can be unloaded by the user if
desired.
kInvkSubrMsg Do invoke the functions registered with acedDefun(). Determine the
function by making a call to acedGetFuncode(). Return values with
acedRetxxx().
Don't do much here except function invocation.
kPreQuitMsg Do unload any dependencies (applications, DLLs, and so on) that your
application controls to ensure that they are unloaded before your
application.
kEndMsg
kCfgMsg
kQuitMsg
Do consider using the AcEditorReactor event callbacks as an alternative
to responding to these messages.
Don't respond to these messages if you're responding to the equivalent
Page 22 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Topics in this section
Sequence of Events in an ObjectARX Application
The process of passing messages between AutoCAD and the ObjectARX application flows almost
completely in one directionfrom AutoCAD to the ObjectARX application. The following diagram shows a
typical sequence for passing messages.
If an application is loaded when a drawing is already open, the kI ni t AppMsg and kLoadDwgMsg
messages are sent in succession. When an ObjectARX application is unloaded while an edit session is in
progress, the kUnl oadDwg and kUnl oadApp messages are sent in succession.
AutoCAD calls into the ObjectARX module through acr xEnt r yPoi nt ( ) , which replaces the mai n( )
function of a C++ program. You are responsible for implementing the acr xEnt r yPoi nt ( ) function, as
described in this section.
The acr xEnt r yPoi nt ( ) function serves as the entry point for AutoCAD (or other host programs) to
communicate with an ObjectARX application. ObjectARX programs can in turn communicate with
AutoCAD by returning status codes. All requests to invoke functions defined with acedDef un( ) are made
by the acr xEnt r yPoi nt ( ) function. If you define a new command with ObjectARX or with the
acedRegFunc( ) function, AutoCAD immediately executes the function associated with the command
(see Loading an ObjectARX Application).
The acr xEnt r yPoi nt ( ) function has the following signature:
kSaveMsg
event callbacks made through AcEditorReactor.
Sequence of Events in an ObjectARX Application
Implementing an Entry Point for AutoCAD
Page 23 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
msg
Represents the message sent from the ObjectARX kernel to the application.
pkt
Holds packet data values.
AppRetCode
Contains the status code returned to AutoCAD.
Within the definition of the acr xEnt r yPoi nt ( ) function, you write a switch statement or similar code to
decipher messages from AutoCAD, perform appropriate actions related to each message, and return an
integer status value.
Warning Using kRet Er r or for the final return value from the acr xEnt r yPoi nt ( ) function will cause
your application to be unloaded, except for the messages kOl eUnl oadAppMsg and kUnl oadAppMsg. In
these cases, if kRet Er r or is returned, the application will not be unloaded.
The following code shows the skeleton of a valid switch statement:
You must initialize any custom classes and commands that your application defines. This initialization
can take place in either the AcRx::kInitAppMsg case of your acr xEnt r yPoi nt ( ) function, or in a
function called from that case.
To initialize an ObjectARX application
1. If you have defined a custom class, invoke its r xI ni t ( ) function.
Defining custom classes is discussed in detail in Deriving a Custom ObjectARX Class
2. If you have defined custom classes, call acr xBui l dCl assHi er ar chy( ) to rebuild the ObjectARX
runtime class tree.
For efficiency, call acr xBui l dCl assHi er ar chy( ) once after calling the r xi ni t ( ) function for each of
your custom classes.
3. Perform any other initialization that you need.
4. Register a service name.
ext er n " C"
AcRx: : AppRet Code
acr xEnt r yPoi nt ( AcRx: : AppMsgCode msg, voi d* pkt ) ;
ext er n " C"
AcRx: : AppRet Code
acr xEnt r yPoi nt ( AcRx: : AppMsgCode msg, voi d* pkt )
{
swi t ch( msg) {
case AcRx: : kI ni t AppMsg:
br eak;
case AcRx: : kUnl oadAppMsg:
br eak;
. . .
def aul t :
br eak;
}
r et ur n AcRx: : kRet OK;
}
Initializing an ObjectARX Application
Page 24 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Registering a service name is suggested if other applications will depend upon your application.
Registering a service name allows other applications to register depending on the service, and allows
your application to check if it has any dependencies before unloading. Registering a service name for
your application is also necessary if you are going to export symbolic functions from your application
using the ObjectARX mechanism. You can use the function acr xRegi st er Ser vi ce( ) , or use the
AcRxSer vi ce class. For more information on registering services, see AcRxService in the ObjectARX
Reference.
5. Register commands with the AutoCAD command mechanism.
Use acedRegCmds- >addCommand( ) to make AutoCAD aware of the commands that your application
defines. For more information, see Registering New Commands.
When your application is unloaded, you must clean up any custom classes or commands that your
application has created. This should take place in the AcRx: : kUnl oadAppMsg case of your
acr xEnt r yPoi nt ( ) function, or in a function called from that case.
To unload an ObjectARX application
1. If you have created commands with the acedRegCmds macro or acedDef un( ) , remove them.
Usually ObjectARX commands are removed by groups, using acedRegCmds- >r emoveGr oup( ) .
2. If you have created custom classes, remove them.
Use the del et eAcRxCl ass( ) function to remove your custom classes from the AcRx runtime tree.
Classes must be removed starting with the leaves of derived classes first, working up the class tree
to parent classes.
3. Delete any objects added by the application.
There is no way to tell AutoCAD to forget about AcDbObj ect instances that are currently resident in
a database. However, when an application is unloaded, AutoCAD will automatically turn such objects
into instances of AcDbPr oxyObj ect or AcDbPr oxyEnt i t y.
4. Remove any reactors that have been attached to any AcDbObj ect , AcDbDat abase,
AcRxDynami cLi nker , or AcEdi t or object. (Persistent reactors on AcDbObj ect s are an exception;
they will become proxy objects when the application is unloaded.)
5. If you have created a service name, remove it.
You can use the acr xSer vi ceDi ct i onar y- >r emove( ) function to remove any service that your
application has registered. See the listing for acr xSer vi ceDi ct i onar y in the ObjectARX Reference.
The following example application implements functions that are called when the application is loaded
and unloaded. Its initialization function adds two new commands to AutoCAD: CREATE and ITERATE.
It also initializes the new class AsdkMyCl ass and adds it to the ObjectARX hierarchy with the
acr xBui l dCl assHi er ar chy( ) function. (AsdkMyCl ass is described in Example of a Custom Object
Class.)
Preparing for Unloading
Example Application
Page 25 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
This section describes adding new commands using the AcEd command registration mechanism. For
information on adding new commands using the functions acedDef un( ) and acedRegFunc( ) , see
ObjectARX Global Utility Functions. For information on adding new commands using the AutoLISP def un
function, see the AutoLISP Developer's Guide.
Topics in this section
Command Stack
Lookup Order
Global versus Local Command Names
Transparent versus Modal Commands
AutoCAD commands are stored in groups in the command stack, which is defined by the
AcEdCommandSt ack class. One instance of the command stack is created per AutoCAD session. This
stack consists of the custom commands that you have defined. The acedRegCmds( ) macro gives you
access to the command stack.
When you add a command, you also assign it a group name. A good policy is to use your registered
developer prefix for the group name to avoid name collisions with other commands. Command names
/ / The i ni t i al i zat i on f unct i on cal l ed f r omt he acr xEnt r yPoi nt ( )
/ / f unct i on dur i ng t he kI ni t AppMsg case i s used t o add commands
/ / t o t he command st ack and t o add cl asses t o t he ACRX cl ass
/ / hi er ar chy.
/ /
voi d
i ni t App( )
{
acedRegCmds- >addCommand( " ASDK_DI CTI ONARY_COMMANDS" ,
" ASDK_CREATE" , " CREATE" , ACRX_CMD_MODAL,
cr eat eDi ct i onar y) ;
acedRegCmds- >addCommand( " ASDK_DI CTI ONARY_COMMANDS" ,
" ASDK_I TERATE" , " I TERATE" , ACRX_CMD_MODAL,
i t er at eDi ct i onar y) ;
AsdkMyCl ass: : r xI ni t ( ) ;
acr xBui l dCl assHi er ar chy( ) ;
}
/ / The cl eanup f unct i on cal l ed f r omt he acr xEnt r yPoi nt ( )
/ / f unct i on dur i ng t he kUnl oadAppMsg case r emoves t hi s appl i cat i on' s
/ / command set f r omt he command st ack and r emoves t hi s appl i cat i on' s
/ / cust omcl asses f r omt he ACRX r unt i me cl ass hi er ar chy.
/ /
voi d
unl oadApp( )
{
acedRegCmds- >r emoveGr oup( " ASDK_DI CTI ONARY_COMMANDS" ) ;
/ / Remove t he AsdkMyCl ass cl ass f r omt he ACRX r unt i me
/ / cl ass hi er ar chy. I f t hi s i s done whi l e t he dat abase i s
/ / st i l l act i ve, i t shoul d cause al l obj ect s of cl ass
/ / AsdkMyCl ass t o be t ur ned i nt o pr oxi es.
/ /
del et eAcRxCl ass( AsdkMyCl ass: : desc( ) ) ;
}
Registering New Commands
Command Stack
Page 26 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
within a given group must be unique, and group names must be unique. However, multiple applications
can add a command of the same name, because the group name makes the commands unambiguous.
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. If you have not already done so, please select a four-character string and
register it at http://www.autodesk.com/symbreg/index.htm .
You usually add commands one at a time with the AcEdCommandSt ack: : addCommand( ) function, and you
remove commands by group with the removeGroup function. You can also use the removeCmd function
to remove commands one at a time. As part of its cleanup before exiting, your application needs to
remove any commands it registered.
The signature for the addCommand( ) function is
cmdGroupName
ASCII representation of the group to add the command to. If the group doesn't exist, it is created
before the command is added.
cmdGlobalName
ASCII representation of the command name to add. This name represents the global or
untranslated name (see Global versus Local Command Names).
cmdLocalName
ASCII representation of the command name to add. This name represents the local or translated
name.
commandFlags
Flags associated with the command. Possible values are ACRX_CMD_TRANSPARENT,
ACRX_CMD_MODAL, ACRX_CMD_USEPICKSET, and ACRX_CMD_REDRAW (see Transparent versus
Modal Commands).
functionAddr
Address of the function to be executed when this command is invoked by AutoCAD.
UiContext
Input pointer to AcEdUI Cont ext callback class.
fcode
Input integer code assigned to the command.
hResourceHandle
Input resource handle to be made current when the command is executed
cmdPtrRet
Input pointer to pointer to be filled in with address of AcEdCommand object for the command
being added
Note It is strongly recommended that all command names be prefixed with your four-letter registered
developer prefix to avoid possible conflicts with commands of the same name in other applications. For
example, the name of a MOVE command for a developer with the prefix ASDK should be ASDKMOVE.
Using your registered developer prefix is also recommended for group names.
Acad: : Er r or St at us
addCommand(
const char * cmdGr oupName,
const char * cmdGl obal Name,
const char * cmdLocal Name,
Adesk: : I nt 32 commandFl ags,
AcRxFunct i onPt r f unct i onAddr ,
AcEdUI Cont ext *UI Cont ext = NULL,
i nt f code=- 1,
HI NSTANCE hResour ceHandl e = NULL,
AcEdCommand** cmdPt r Ret = NULL) ;
Page 27 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
When a command is invoked, the command stack is searched by group name, then by command name
within the group. In general, the first group registered will be the first one searched, but you cannot
always predict what this order will be. Use the AcEdCommandSt ack: : popGr oupToTop( ) function to
specify that a particular group should be searched first. At the user level, the Group option of the ARX
command allows the user to specify which group to search first.
When you add a command to AutoCAD, you need to specify both a global name that can be used in any
language and a localized name that is a translated version of the command name to be used in a
foreign-language version of AutoCAD. If you don't need to translate the command name into a local
language, the same name can be used for both the global and local names.
A command can be either transparent or modal. A transparent command can be invoked when the user
is being prompted for input. A modal command can be invoked only when AutoCAD is posting the
command prompt and no other commands or programs are currently active. The commandFl ags
argument to the AcEdCommandSt ack: : addCommand( ) function specifies whether the new command is
modal (ACRX_CMD_MODAL) or transparent (ACRX_CMD_TRANSPARENT). The commandFl ags argument
also specifies other options for the command. See AcEdCommandSt ack in the ObjectARX Reference.
Transparent commands can be nested only one level (that is, the main command is invoked, which
invokes one transparent command).
If you create multiple commands that operate on a common set of global objects, consider whether you
should make them modal so that they won't interfere with each other. If such collisions are not a
problem, making new commands transparent results in greater flexibility of use.
You can load an ObjectARX application using any of the following methods:
Provide the application with features that allow it to be demand loaded by AutoCAD . These features
include application-specific entries in the Windows system registry. See Demand Loading.
Specify the application in the initial module file, acad.rx. This file contains ASCII text with the names
of all programs AutoCAD should load when it is started. Each line in the file contains a program
name (with the path if the file is not in a directory on the AutoCAD library search path). The acad.rx
file must also be in a directory on the AutoCAD search path.
Make an application load request from another ObjectARX application using
AcRxDynami cLi nker : : l oadModul e( ) .
Use the APPLOAD command.
Create a BUNDLE and deploy it to the ApplicationPlugins folder. See Application Automatic Loading.
Use the ar xl oad( ) function from AutoLISP.
Use the acedAr xLoad( ) function from ObjectARX.
Lookup Order
Global versus Local Command Names
Transparent versus Modal Commands
Loading an ObjectARX Application
Page 28 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Enter the ARX command on the AutoCAD command line and use the Load option.
Start AutoCAD from the DOS command line using the / l d or - l d switch followed by the path and file
name of the ObjectARX application or Object Enabler. For example:
If the entry does not include a full path, AutoCAD will look for the specified file on the ACAD search
path.
This switch may be used more than once per startup command line, and other switches may be
interspersed. For example:
If the path or file name contains spaces, the path and file name should be wrapped in quotes. For
example:
Topics in this section
The Library Search Path
Listing Loaded ObjectARX Applications
If you don't specify a search path, loading functions such as ar xl oad search for the application in the
directories specified by the AutoCAD library path. The AutoCAD library path includes the following
directories in the order shown:
1. The current directory.
2. The directory that contains the current drawing file.
3. The directories specified by the support path (see the AutoCAD Customization Guide).
4. The directory that contains the AutoCAD program files.
To see the names of all the ObjectARX programs currently loaded, use the Commands option of the ARX
command. For more information, see ARX Command. The APPLOAD command opens a dialog that also
lists the names of the ObjectARX programs currently loaded.
You can unload an ObjectARX application with any of the following methods (if it is unlocked):
Make an application unload request from another ObjectARX application using
AcRxDynami cLi nker : : unl oadModul e( ) .
Use the APPLOAD command. This opens a dialog that allows you to load and unload applications.
/ l d c: \ myf i l es\ t est . ar x or - l d t est . ar x.
acad / l d t est 1. ar x / l d c: \ myf i l es\ t est 2. ar x / nol ogo / l d t est 3. ar x
/ l d " c: \ my f i l es\ t est . ar x"
The Library Search Path
Listing Loaded ObjectARX Applications
Unloading an ObjectARX Application
Page 29 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Remove a BUNDLE from the ApplicationPlugins folder. See Application Automatic Loading.
Use the ar xunl oad function from AutoLISP.
Use the acedAr xUnl oad( ) function from ObjectARX.
Enter the ARX command on the AutoCAD command line and use the Unload option.
Topics in this section
Unlocking Applications
By default, applications are locked and cannot be unloaded. To be classified as an unloadable
application, the application must ensure that AutoCAD and other applications no longer refer to any
objects or structures the application has defined. Before you make an application unloadable, be very
careful that no client applications contain active pointers to any objects in your address space. For the
list of cleanup operations an application must perform to be unloadable, see Preparing for Unloading.
If you want to make your application unloadable, you need to store the value of the pkt parameter sent
with the AcRx: : kI ni t AppMsg. The pkt parameter will be used by the unl ockAppl i cat i on( ) function. By
default, an application is locked. If you unlock an application, it can be unloaded.
Use the following two functions to lock and unlock an application:
The following function checks whether or not an application is locked:
Analogous global functions are also provided:
ObjectARX applications can be loaded as part of a plug-in using a package format, which is a common
folder structure with a .bundle extension. Each package can contain the files required to deploy an
application and register the commands contained in the application. A package is loaded into AutoCAD
by placing it in one of the ApplicationPlugins folders on your local drive.
Unlocking Applications
vi r t ual bool
AcRxDynami cLi nker : : l ockAppl i cat i on( voi d* pkt ) const = 0;
vi r t ual bool
AcRxDynami cLi nker : : unl ockAppl i cat i on( voi d* pkt ) const = 0;
vi r t ual bool
AcRxDynami cLi nker : : i sAppl i cat i onLocked( const char * name) const = 0;
bool
acr xLockAppl i cat i on( voi d* pkt ) ;
bool
acr xUnl ockAppl i cat i on( voi d* pkt ) ;
bool
acr xAppl i cat i onI sLocked( const char * modul ename) ;
Application Automatic Loading
Page 30 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
The APPAUTOLOAD system variable controls when AutoCAD looks in and loads the plug-ins from the
ApplicationPlugins folders. If APPAUTOLOAD is set to 0, plug-ins can be loaded using the
APPAUTOLOADER command.
For information on deploying an application with the package format, see Install and Uninstall Plug-In
Applications in the Customization Guide.
Demand loading is a feature of AutoCAD that automatically attempts to load an ObjectARX application
that is not resident in AutoCAD. ObjectARX applications can be designed for loading by AutoCAD under
one or more of the following circumstances:
When a drawing file that contains custom objects created by the absent application is read
When a user or another application issues one of the absent application's commands
When AutoCAD is started
Note Applications that implement demand loading on AutoCAD startup will be loaded before those listed
in acad.rx.
Autodesk recommends developing ObjectARX applications that take advantage of AutoCAD's demand-
loading feature because demand loading provides the following benefits:
Limits the creation of proxy objects (see Proxy Objects)
Provides greater flexibility for loading ObjectARX applications
Conserves memory by loading applications only when their functionality is required
For an application to be accessible for demand loading, application-specific information must be present
in the Windows system registry. In addition, ObjectARX applications with more than one DLL may need
a controller module that is responsible for loading all other components of the application. Finally, the
DEMANDLOAD system variable must be set to the appropriate value for demand loading.
Note
An ObjectARX application can be demand loaded from a path on the local machine, or by using an
Internet address.
Topics in this section
AutoCAD, the Windows System Registry, and ObjectARX Applications
Modification of the Registry at ObjectARX Application Installation
The DEMANDLOAD System Variable
Demand Loading on Detection of Custom Objects
Demand Loading on Command
Demand Loading on AutoCAD Startup
Demand Loading on Context Menu Invocation
Loading .NET Applications on AutoCAD Startup
Using ObjectARX APIs to Simplify Registry Setup
Code Sample: Writing Demand Loading Keys
Managing Applications with the System Registry
Demand Loading
AutoCAD, the Windows System Registry, and ObjectARX Applications
Page 31 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
AutoCAD uses the Windows system registry to maintain a wide range of application information,
including information that uniquely identifies different AutoCAD releases, language versions, and
products (such as AutoCAD Map ) that may be installed on any given computer. The registry information
that identifies different versions of AutoCAD is of particular significance for ObjectARX developers. The
installation program for an ObjectARX application must associate information about that ObjectARX
application with information about the version(s) of AutoCAD with which it is supposed to run.
The AutoCAD installation program creates a unique time stamp key in the system registry immediately
below the release number key (as well as adding the same installation ID to the executable itself). This
key ensures that different versions of AutoCAD from the same release will be able to populate their own
sections of the system registry. Within this key, values are stored for attributes such as the location of
AutoCAD files and the language version, as illustrated in this example:
The installation program for an ObjectARX application must be able to locate the appropriate AutoCAD
release key, as well as the appropriate language and product values.
The time stamp key is also used to identify the version of AutoCAD that is currently loaded (or the
version that was most recently loaded). This identification is necessary, because the current version of
AutoCAD resets the information in the global HKEY_CLASSES_ROOT section of the registry for its own use
when it is loaded.
The Cur Ver value in the release key section of the registry is used to identify the current version, for
example:
AutoCAD uses the Windows system registry to locate ObjectARX applications for demand loading. A part
of the AutoCAD section of the registry is used for information about the location of ObjectARX
applications' registry information.
The installation program for an ObjectARX application must create the specific keys and values in the
system registry that are required for demand loading. Some of the required keys and values must be
created in the AutoCAD section of the registry, and others must be created in the ObjectARX
application's section of the registry.
If the ObjectARX application is designed to run with more than one version of AutoCAD (that is, different
language versions or related products, such as AutoCAD Map), the installation program must add the
appropriate information to the section of the registry for each version of AutoCAD.
The installation process for ObjectARX applications must therefore include:
Verification that the sections of the system registry for the appropriate version of AutoCAD exist. (If
the AutoCAD section of the registry does not exist, the user should be warned that a compatible
version of AutoCAD has not been installed, and the installation should be aborted.)
Creation of a specific set of keys and values for the application within the section(s) of the system
registry for the appropriate version(s) of AutoCAD.
\ \ HKEY_LOCAL_MACHI NE\ SOFTWARE\ Aut odesk\ Aut oCAD\ R20. 0\
ACAD- E001: 409\
. . .
Language: REG_SZ: Engl i sh
Locat i on: REG_SZ: C: \ Pr ogr amFi l es\ Aut odesk\ Aut oCAD <
> . . .
release_name
\ \ HKEY_CURRENT_USER\ Sof t war e\ Aut odesk\ Aut oCAD\ R20. 0\
Cur Ver : REG_SZ: ACAD- E001: 409
Modification of the Registry at ObjectARX Application Installation
Page 32 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Creation of a major key for the application itself, and population of that key with another set of
specific keys and values.
See the samples\entity\polysamp\demandload directory of the ObjectARX SDK for information about
how the system registry is modified for demand loading the sample program polysamp.
The following sections describe how an application's installation program should create the system
registry information required for demand loading. The ObjectARX samples\entity\polysamp\setup
directory contains sample installer projects.
Topics in this section
Accommodating Windows Privilege Levels
Creating AutoCAD Subkeys and Values
If the current Windows user is not a power user, neither AutoCAD nor the applications running under it
can write to the HKEY_LOCAL_MACHI NE area of the registry. To handle this scenario, AutoCAD supports
demand load entries in both the HKEY_LOCAL_MACHI NE and HKEY_CURRENT_USER registry sections.
For demand loading, AutoCAD first looks for entries under HKEY_CURRENT_USER. If the necessary entries
are found there, they are used. If the entries are not found under HKEY_CURRENT_USER, AutoCAD looks
under HKEY_LOCAL_MACHI NE.
ObjectDBX also follows the AutoCAD registry search rules described in this section.
ObjectARX provides APIs that simplify the process of writing to the correct area of the registry. See
Using ObjectARX APIs to Simplify Registry Setupfor more information on these APIs.
The ObjectARX application's installation program must be designed to manage a set of keys and values
for that application within the section of system registry for each version of AutoCAD with which it is
intended to run. This section of the registry must include keys and values identifying the main module of
the application and the command set for the application.
The following example shows the layout of the keys and values in the section of the registry that must
be created and maintained for the application:
Accommodating Windows Privilege Levels
Creating AutoCAD Subkeys and Values
\ \ HKEY_LOCAL_MACHI NE\ SOFTWARE\ Aut odesk\ Aut oCAD\ r el easeNum\
ACAD- Pr oduct I D: Local eI D\
Appl i cat i ons\
Appl i cat i onName\
DESCRI PTI ON: REG_SZ: User Fr i endl y App Name
LOADCTRLS: REG_DWORD: acr xAppLoadReason
LOADER: REG_SZ: Di r Pat hFi l eName
Commands\
Gl obal CommandName1: REG_SZ: Local CommandName1
Gl obal CommandName2: REG_SZ: Local CommandName2
Gl obal CommandName3: REG_SZ: Local CommandName3
Gl obal CommandName4: REG_SZ: Local CommandName4
Gl obal CommandName5: REG_SZ: Local CommandName5
Gr oups\
Gr oupName: REG_SZ: Gr oupName
. . .
Page 33 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
The r el easeNumand ACAD- Pr oduct I D: Local eI D keys are created by the AutoCAD installation program.
The Appl i cat i onName key must be the logical name of the application, which is used internally by
AutoCAD to identify the program.
The value in the LOADER key must include the full path and file name of the module that AutoCAD should
load first. The loader module is subsequently responsible for loading any other modules that make up
the application.
The acr xAppLoadReason value defines the conditions under which the application will be loaded, using
one or more logical ORs of the following hex values listed with their associated meanings:
0x01
Load the application upon detection of proxy object.
0x02
Load the application upon AutoCAD startup.
0x04
Load the application upon invocation of a command.
0x08
Load the application upon request by the user or another application.
0x10
Do not load the application.
0x20
Load the application transparently.
The value in the Gr oups key may be used to uniquely identify an ObjectARX application's command
groups and therefore the commands as well.
The acr xRegi st er App( ) global function may be used in an ObjectARX application to enter information
about the application into the AutoCAD section of the system registry. Typically, acr xRegi st er App( )
would enter this information the first time the application is loaded, and confirm the presence of that
information on subsequent loads.
The AutoCAD DEMANDLOAD system variable controls the demand loading options of ObjectARX
applications.
By default the DEMANDLOAD system variable is set (when AutoCAD is installed) to enable demand
loading of applications on command invocation or on proxy detection, when either option is specified in
the system registry entry for an application. The setting of DEMANDLOAD does not affect demand
loading on AutoCAD startup, or on request by a user or application when either of these options is
specified in the system registry. (See Creating AutoCAD Subkeys and Values).
The legitimate values for the system variable may be used in combination. They are defined as follows:
0
Disables demand loading of all ObjectARX applications.
1
Enables demand loading of ObjectARX applications upon detection of proxy objects.
2
Enables demand loading of ObjectARX applications upon command invocation.
The DEMANDLOAD System Variable
Page 34 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
3
Enables demand loading for both proxy objects and command invocation (the default).
The DEMANDLOAD system variable allows the user to disable demand loading of all ObjectARX
applications that have system registry settings specifying demand loading on command invocation and
proxy detection. It cannot cause an application to be demand loaded if the appropriate system registry
settings do not exist.
When a DWG or DXF file containing custom objects is loaded, AutoCAD determines whether or not the
associated application is loaded. If the application is not loaded, and the first bit of the system variable
DEMANDLOAD is set, AutoCAD searches the Windows system registry for information about the
application and its loader module. If AutoCAD finds the appropriate information in the system registry, it
loads the application.
Note Demand loading on detection of custom classes will only work with classes that are derived from
AcDbObj ect , either directly or indirectly.
As a hypothetical example, let's assume that AutoCAD reads a file created by the ObjectARX application
polysamp (a product of PolySamp Inc.).
1. Upon reading the drawing file, AutoCAD encounters custom objects created with the application
polysamp, and determines that the application is not loaded.
2. AutoCAD finds that the DEMANDLOAD system variable is set to enable demand loading of
applications on proxy detection, so it searches the AutoCAD Applications section of the system
registry for the pol ysamp key. Within this key, it finds the LOADCTRLS value, which defines the
conditions under which the application should be loaded. This section of the registry would look
something like this:
AutoCAD then attempts to load the ObjectARX module. If the module loads successfully, AutoCAD adds
the application's handle to the list of application handles to be sent the kLoadDwgMsg message.
AutoCAD then verifies that the application has been loaded properly, and verifies that the custom class
is registered. If the application was loaded successfully, AutoCAD will continue to load the drawing file.
If the ObjectARX module cannot be loaded, or if there still isn't a class implementation available, custom
objects are treated as proxies and the load continues.
AutoCAD will attempt to load the appropriate ObjectARX application if the user invokes a command that
is not registered with AutoCAD.
To support demand loading on command invocation, the ObjectARX application's installation program
must create the appropriate keys and values in the system registry for the application's commands. The
application's Commands section of the system registry should contain command information like this:
Demand Loading on Detection of Custom Objects


\ \ 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

session begins, the database contains the following elements:


A set of nine symbol tables.
Block table (AcDbBl ockTabl e)
Dimension style table (AcDbDi mSt yl eTabl e)
Layer table (AcDbLayer Tabl e)
Linetype table (AcDbLi net ypeTabl e)
Registered applications table (AcDbRegAppTabl e)
Text style table (AcDbText St yl eTabl e)
User Coordinate System table (AcDbUCSTabl e)
Viewport table (AcDbVi ewpor t Tabl e)
View table (AcDbVi ewTabl e)
Some of the symbol tables already contain one or more records. The layer table in a pristine
database contains one record, layer 0. The block table initially contains three records:
*MODEL_SPACE, *PAPER_SPACE, and *PAPER_SPACE0. The linetype table always has
CONTINUOUS, BY_LAYER, and BY_BLOCK linetype table records. The registered applications table
always has an ACAD table record. The text style table always has a STANDARD table record.
A named object dictionary. When a database is created, this dictionary already contains the two
database dictionaries: the GROUP dictionary and the MLINE style dictionary. Within the MLINE style
dictionary, the STANDARD style is always present.
A fixed set of header variables. (These are not database objects.)
Use new to create a database and del et e to destroy one. The first argument in the AcDbDat abase
constructor has a default value of Adesk: : kTr ue. If this argument is Adesk: : kTr ue, then the database
is populated with the standard database objects, described in Initial DatabaseIf the argument is
Adesk: : kFal se, then an empty database is created and can be populated by reading in a drawing file.
Use readDwgFile to read in a drawing file.
If you receive any of the following error codes, you probably want to recover the drawing with the
standard AutoCAD recover mechanism provided by the user interface:
Initial Database
Creating and Populating a Database
kDwgNeedsRecover y
kDwgCRCDoesNot Mat ch
kDwgSent i nel DoesNot Mat ch
kDwgObj ect I mpr oper l yRead
Page 45 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Warning Never delete the database returned by the acdbHost Appl i cat i onSer vi ces( ) -
>wor ki ngDat abase( ) function.
To save a database, use the saveAs function. You can also choose to save the file in the previous file
format using the global function acdbSaveAs2000.
Topics in this section
Setting the Default File Format
ObjectARX

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

database objects, including entities, symbol


table records, and dictionaries. Major concepts included are opening and closing objects, managing
objects in memory, object ownership, and extending an object using xdata or the object's extension
dictionary. Other common operations on objects, such as filing and erasing, are also discussed.
Topics in this section
Opening and Closing Database Objects
Deleting Objects
Database Ownership of Objects
Adding Object-Specific Data
Erasing Objects
Object Filing
Embedded and Encapsulating Objects
Each AcDbObj ect object can be referred to in three different ways:
By its handle
By its object ID
By a C++ instance pointer
When AutoCAD is not running, the drawing is stored in the file system. Objects contained in a DWG file
are identified by their handles.
After the drawing is opened, the drawing information is accessible through the AcDbDat abase object.
Each object in the database has an object ID, which persists throughout the current edit session, from
creation until deletion of the AcDbDat abase in which the object resides. The open functions take an
object ID as an argument and return a pointer to an AcDbObj ect object. This pointer is valid until the
object is closed, as shown in the following figure.
You can open an object using the acdbOpenObject global function.
You can map a handle to an object ID using the getAcDbObjectId function.
Database Objects
Opening and Closing Database Objects
Page 60 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
You can also open an object and then request its handle:
Note Whenever a database object is opened, it should be closed at the earliest possible opportunity.
You can use the AcDbObj ect : : cl ose( ) function to close a database object.
An ads_name is equivalent to an AcDbObj ect I d. The AcDb library provides two standalone functions that
allow you to translate between an AcDbObj ect I d and an ads_name:
Generally, you obtain an object through a selection, and it is returned in ads_name form. You then need
to exchange the ads_name for an AcDbObj ect I d and open it. The following function demonstrates this
process:
You can open an object in one of three modes:
kFor Read. An object can be opened for read by up to 256 readers as long as the object is not
already open for write or for notify.
kFor Wr i t e. An object can be opened for write if it is not already open. Otherwise, the open fails.
kFor Not i f y. An object can be opened for notification when the object is closed, open for read, or
open for write, but not when it is already open for notify. See NotificationApplications will rarely
need to open an object for notify and send it notification.
The following table shows the error codes returned when you attempt to open an object in different
modes and the object is already open.
AcDbObj ect * pObj ect ;
AcDbHandl e handl e;
pObj ect - >get AcDbHandl e( handl e) ;
/ / Ret ur ns an ads_name f or a gi ven obj ect I D.
/ /
acdbGet AdsName( ads_name& obj Name,
AcDbObj ect I d obj I d) ;
/ / Ret ur ns an obj ect I D f or a gi ven ads_name.
/ /
acdbGet Obj ect I d( AcDbObj ect I d& obj I d,
ads_name obj Name) ;
AcDbEnt i t y*
sel ect Ent i t y( AcDbObj ect I d& eI d, AcDb: : OpenMode openMode)
{
ads_name en;
ads_poi nt pt ;
acedEnt Sel ( " \ nSel ect an ent i t y: " , en, pt ) ;
/ / Exchange t he ads_name f or an obj ect I D.
/ /
acdbGet Obj ect I d( eI d, en) ;
AcDbEnt i t y * pEnt ;
acdbOpenObj ect ( pEnt , eI d, openMode) ;
r et ur n pEnt ;
}
Opening objects in
different modes
Object already
opened for:
kForRead kForWrite kForNotify
openedForRead eAtMaxReaders
(if readCount = 256;
otherwise succeeds)
eWasOpenForRead (Succeeds)
openedForWrite eWasOpenForWrite eWasOpenForWrite (Succeeds)
Page 61 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
If you are trying to open an object for write and you receive an error eWasOpenFor Read, you can use
upgr adeOpen( ) to upgrade the open status to write if there is only one reader of the object. Then you
would use downgr adeOpen( ) to downgrade its status to read. Similarly, if your object is open for
notifyfor example, when you are receiving notificationand you want to open it for write, you can use
upgr adeFr omNot i f y( ) to upgrade its open status to write. Then you would use downgr adeToNot i f y( )
to downgrade its status to notify.
For more information about how to manage complex sequences of opening and closing objects, see
Transaction Manager.
When you create an instance of an AcDbObj ect object with the intent of appending it to the database,
use the AcDbObj ect : : new( ) function. When an object is first created and has not yet been added to the
database, you can delete it. However, once an object has been added to the database, you cannot
delete it; AutoCAD manages the deletion of all database-resident objects.
An object that is implicitly owned by the database rather than another database object is called a root
object. The database contains ten root objects: the nine symbol tables and the named object dictionary.
All filing operations begin by filing out the root objects of the database. See Object Filing.
With the exception of root objects, every object in the database must have an owner, and a given object
can have only one owner. The database is a tree created by this hierarchy of owned objects. The
following call adds an object to the database and assigns an ID to it, but the object does not yet have
an owner:
Usually, you will add the object to its owner using a member function that simultaneously adds it to the
database, such as the AcDbBl ockTabl eRecor d: : appendAcDbEnt i t y( ) function, which performs both
tasks at once.
AutoCAD ownership connections are as follows:
The block table records own entities.
Each symbol table owns a particular type of symbol table record.
An AcDbDi ct i onar y object can own any AcDbObj ect object.
Any AcDbObj ect object can have an extension dictionary; an object owns its extension dictionary.
In addition, applications can set up their own ownership connections.
openedForNotify eWasOpenForNotify eWasOpenForNotify eWasOpenForNotify
wasNotifying (Succeeds) eWasNotifying eWasNotifying
Undo eWasOpenForUndo eWasOpenForUndo (Succeeds)
Deleting Objects
Database Ownership of Objects
db- >addAcDbObj ect ( . . . ) ;
Adding Object-Specific Data
Page 62 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
You can use any of four mechanisms for adding instance-specific data in your application:
Extended data (xdata)
Xrecords (see Container Objects)
Extension dictionaries of any object
Custom objects that can hold data
Topics in this section
Extended Data
Extension Dictionary
Extended data (xdata) is created by applications written with ObjectARX

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

automatically invokes the


AcDbEnt i t y: : set Dat abaseDef aul t s( ) function, which sets the properties to their default values if you
have not explicitly set them.
AcDbVi ewpor t acquires the settings of the current graphics window.
If a property has not been explicitly specified for an entity, the database's current value for that
property is used. See Database Operationsfor a description of the member functions used for setting
and getting the current property values associated with the database.
Topics in this section
Entity Color
Entity Linetype
Entity Linetype Scale
Entity Visibility
Entity Layer
Common Entity Properties
Page 76 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Entity color can be set and read as numeric index values ranging from 0 to 256, or by instances of
AcCmCol or . The correct color index can be obtained from an instance of AcCmCol or using the
AcCmCol or : : get Col or I ndex( ) member function.
Color indexes 1 through 7 are used for standard colors, as shown in the following table
:
Colors 8 through 255 are defined by the display device.
The following index values have special meanings:
0
Specifies BYBLOCK. Entities inherit the color of the current block reference that points to the block
table record that the entity resides in, or black/white if the entity resides directly in the model
space or paper space block table record.
256
Specifies BYLAYER. Entities assume the color of the entity's associated layer.
257
No color. Only present from the time an entity is first instantiated until its color is set to a value
between 0 and 256, or the entity is added to the database and assumes the database's current
color index.
If a color value is specified for an entity, the current database default color value is ignored. Use the
following functions to set and query an entity color:
setColor
setColorIndex
color
colorIndex
The linetype value points to a symbol table entry that specifies a series of dots and dashes used for
Entity Color
Colors 1 to 7
Color Number Color Name
1 Red
2 Yellow
3 Green
4 Cyan
5 Blue
6 Magenta
7 White or Black
Entity Linetype
Page 77 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
drawing lines. When an entity is instantiated, its linetype is set to NULL. When the entity is added to the
database, if a linetype has not been specified for the entity, the linetype is set to the database's current
linetype value. This default value is stored in the CELTYPE system variable. Linetype can be specified by
name, by a string, or by the object ID of an AcDbLi neTypeTabl eRecor d in the entity's target database.
Special linetype entries are as follows:
CONTINUOUS
Default linetype, which is automatically created in the linetype symbol table
BYLAYER
Linetype value of the entity's layer
BYBLOCK
Linetype value of the entity's surrounding block definition's current block reference
If a linetype value is specified for an entity, the current database default linetype value is ignored.
The setLinetype functions enable you to set the linetype for an entity, either by name or by object ID.
The linetype function returns the name of the current entity linetype, and the linetypeId funtion returns
the object ID for the symbol table record specifying the linetype.
When an entity is first instantiated, its linetype scale is initialized to an invalid value. When the entity is
added to the database, if a linetype scale has not been specified for the entity, it is set to the database's
current linetype scale value. This database default value is stored in the CELTSCALE system variable.
Linetype Scale Specified Per Entity
If a linetype scale value is specified for an entity, the current database default linetype scale value is
ignored.
The setLinetypeScale and linetypeScale functions allow you to set and inquire the linetype scale for an
entity:
Regenerating a Drawing
When an entity is regenerated, its effective linetype scale is a product of both the entity linetype scale
and the global database linetype scale. For nonpaper space entities, the linetype scale is calculated as
follows:
If PSLTSCALE is 1, the effective linetype scale is then applied to the appearance of the model space
entity when viewed in paper space. If PSLTSCALE is 0, then all linetype scaling is performed with
respect to model space views. See the AutoCAD User's Guide for further explanation of linetype scales.
If you specify that an entity is invisible, it will be invisible regardless of other settings in the database.
Other factors can also cause an entity to be invisible. For example, an entity will not be displayed if its
layer is turned off or frozen. The value of AcDb: : Vi si bi l i t y can be either kI nvi si bl e or kVi si bl e.
Entity Linetype Scale
ef f l t scal e = ent - >l i net ypeScal e( ) *
ent - >dat abase( ) - >l t scal e( ) ;
Entity Visibility
Page 78 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
The setVisibility and visibility functions allow you to set and inquire the visibility for an entity.
All entities have an associated layer. The database always contains at least one layer (layer 0). As with
linetypes, you can specify a layer for an entity. If you don't specify a layer, the default database layer
value is used for a new entity.
Each layer also has associated properties, which include frozen/thawed, on/off, locked/unlocked, color,
linetype, and viewport (see Container Objects). When an entity's color or linetype is BYLAYER, the value
of the layer property is used for the entity.
If a layer value is specified for an entity, the current database layer value is ignored.
The setLayer functions enable you to set the layer for an entity, either by name or by object ID.
The layer function returns the name of the current entity layer.
The layerId function returns the object ID for the current layer (an object of type
AcDbLayer Tabl eRecor d).
Entities also have a number of common functions, primarily intended for use by AutoCAD. This section
provides general background on using some of these functions. For examples of implementing the
functions for new classes, see Deriving from AcDbEntity
Common entity functions include the following:
i nt er sect Wi t h( ) is used in trim, extend, fillet, chamfer, break, and object snap Intersection
operations
t r ansf or mBy( ) is used to pass in a transform matrix that moves, scales, or rotates points in the
object
get Tr ansf or medCopy( ) creates a copy of the object and applies a transformation to it
get OsnapPoi nt s( ) returns the snap points and the kind of snap points
get Gr i pPoi nt s( ) returns the grip points, which are a superset of the stretch points
get St r et chPoi nt s( ) defaults to get Gr i pPoi nt s( ) and usually has the same implementation
moveSt r et chPoi nt sAt ( ) is used by the AutoCAD STRETCH command to move specified points and
defaults to t r ansf or mBy( )
moveGr i pPoi nt sAt ( ) is used by AutoCAD grip editing to move specified points and defaults to
t r ansf or mBy( )
wor l dDr aw( ) c reates a view-independent geometric representation of an entity
vi ewpor t Dr aw( ) c reates a view-dependent geometric representation of an entity
dr aw( ) q ueues up the entity and flushes the graphics queue so that the entity and anything else in
the queue are drawn
l i st ( ) is used by the AutoCAD LIST command and produces acut Pr i nt f ( ) statements
get GeomExt ent s( ) returns the corner points of a box that encloses the 3D extents of your entity
expl ode( ) d ecomposes an entity into a set of simpler elements
Entity Layer
Common Entity Functions
Page 79 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
get Subent Pat hsAt GsMar ker ( ) returns the subentity paths that correspond to the given GS marker
(see GS Markers and Subentities)
get GsMar ker sAt Subent Pat h( ) returns the GS marker that corresponds to the given subentity path
subent Pt r ( ) r eturns a pointer corresponding to the given subentity path
hi ghl i ght ( ) highlights the specified subentity (see GS Markers and Subentities)
Topics in this section
Object Snap Points
Transform Functions
Intersecting for Points
GS Markers and Subentities
Exploding Entities
Annotation Scaling
Objects can have certain characteristic points defined for them, such as a center point, midpoint, or
endpoint. When AutoCAD is acquiring points and is in Object Snap mode, it invokes the getOsnapPoints
function to acquire the relevant snap points for the specified Object Snap mode. The following table lists
the possible Object Snap modes.
The AcDbEnt i t y class provides two transformation functions:
transformBy
getTransformedCopy
Object Snap Points
Object Snap modes
Mode Description
kOsModeEnd Endpoint
kOsModeMi d Midpoint
kOsModeCen Center
kOsModeNode Node
kOsModeQuad Quadrant
kOsModeI ns Insertion
kOsModePer p Perpendicular
kOsModeTan Tangent
kOsModeNear Nearest
Transform Functions
Page 80 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
The t r ansf or mBy( ) function modifies the entity using the specified matrix. In AutoCAD, it is called by
the grip move, rotate, scale, and mirror modes. In some cases, however, applying the transformation
requires that a new entity be created. In such cases, the get Tr ansf or medCopy( ) function is used so
that the resulting entity can be an instance of a different class than the original entity.
When you explode a block reference that has been nonuniformly scaled, the get Tr ansf or medCopy( )
function is called on the entities in the block reference to create the new entities (see Exploding
Entities).
The i nt er sect Wi t h( ) function returns the points where an entity intersects another entity in the
drawing. Input values for this function are the entity and the intersection type, which can be one of the
following:
kOnBot hOper ands (neither entity is extended)
kExt endThi s
kExt endAr g
kExt endBot h
For example, suppose a drawing contains the three lines shown in the following illustration. Line1 is
this and line3 is the argument entity. If the intersection type is kExt endThi s, point A is returned as
the point where line1 (this) would intersect line3 if line1 were extended. If the intersection type is
kExt endAr gument and line2 is the argument entity, no data is returned because, even if it were
extended, line2 would not intersect line1. If the intersection type is kExt endBot h and line2 is the
argument entity, point B is returned. If the intersection type is kExt endNone and line2 is the argument
entity, no data is returned.
The i nt er sect Wi t h( ) function is an overloaded function with two forms. The second form takes an
additional argument, which is a projection plane for determining the apparent intersection of two
entities. These are the signatures for the i nt er sect Wi t h( ) function:
Intersecting for Points
Page 81 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
The returned points are always on the entity (this). Therefore, in cases of apparent intersection, the
intersected points are projected back to the entity before they are returned.
Both versions of the i nt er sect Wi t h( ) function allow you to supply optional GS markers to optimize
performance for this function. If the entity's i nt er sect Wi t h( ) function has implemented the use of GS
markers, then supplying GS markers can localize the intersection area and speed up the test. For
example, in the following drawing, if the user selects one line of the polygon, passing in the GS marker
for that line eliminates the need to test the other five lines of the polygon.
To draw itself, every entity makes calls to graphics primitives such as polylines, circles, and arcs,
contained in the AcGi library. Any class derived from AcDbEnt i t y can associate a graphics system (GS)
marker with the display vectors it uses to draw itself. Each entity subclass controls where it inserts its
GS markers. When a user selects an entity, the GS marker is used to identify which part of the entity
was picked.
Solids derived from AcDb3dSol i d are composed of vertices, edges, and faces. Each of these elements
can be identified by a GS marker. The creator of the entity class decides where GS markers should be
inserted, depending on what is most natural for the entity. A box, for example, creates a GS marker for
each line used to draw the box. A cylinder creates three GS markersone for its top, bottom, and
outside faces.
An entity is composed of subentities of the following type: vertex, edge, or face. Currently, the only
entities that support subentities are bodies, regions, solids, and mlines. Use the
get Subent Pat hsAt GsMar ker ( ) function to obtain the paths to the subentities that are associated with a
particular GS marker. More than one subentity can be associated with a single marker. In the case of
vi r t ual Acad: : Er r or St at us
AcDbEnt i t y: : i nt er sect Wi t h(
const AcDbEnt i t y* ent ,
AcDb: : I nt er sect i nt Type,
AcGePoi nt 3dAr r ay& poi nt s,
i nt t hi sGsMar ker = 0,
i nt ot her GsMar ker = 0) const ;
vi r t ual Acad: : Er r or St at us
AcDbEnt i t y: : i nt er sect Wi t h(
const AcDbEnt i t y* ent ,
AcDb: : I nt er sect i nt Type,
const AcGePl ane& pr oj Pl ane,
AcGePoi nt 3dAr r ay& poi nt s,
i nt t hi sGsMar ker = 0,
i nt ot her GsMar ker = 0) const ;
GS Markers and Subentities
Page 82 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
the box, for example, marker 4 identifies the lower front edge of the box. If you ask for the vertices
associated with this marker, the two vertices that form the endpoints of this line are returned. If you
ask for the edges associated with this marker, one entitythe lineis returned. If you ask for the faces
associated with this marker, data for the front face and the bottom face of the box are returned.
Warning
AutoCAD's 2D graphics system does not support the use of selection markers with drawing objects
whose subentities are on more than one layer. If you use selection markers for a drawing object, all
graphics subentities for that object must reside on a single layer. If you must use multiple layers for an
object's subentities, do not use selection markers.
Topics in this section
Subentity Path
Simple Highlighting Example
Highlighting Nested Block References
A subentity path uniquely identifies a subentity within a particular entity in a drawing. This path, of class
AcDbFul l Subent Pat h, consists of an array of object IDs and a subentity ID object:
The array contains the object IDs that specify the path to the main entity. For example, a block
reference (an entity that references a block table record) might contain two boxes, each of type
AcDb3dSol i d. The object ID array contains two entries: the ID of the block reference, followed by the ID
of the main entity [InsertID, SolidID].
The second element of an AcDbFul l Subent Pat h is an AcDbSubent I d object, which has a subentity type
(vertex, edge, or face) and the index of the subentity in the list. Use the AcDbSubent I d functions t ype
( ) and i ndex( ) to access the member data.
Using the previous example, the second edge of the solid will have its AcDbFul l Subent Pat h as
If you have a solid only, AcDbFul l Subent Pat h would be as follows for the first face of the solid.
The code example later in this section shows how to highlight a subentity. The following procedure lists
the basic steps.
To highlight a subentity
Subentity Path
{AcDbObj ect I dAr r ay mObj ect I ds;
AcDbSubent I d mSubent I d;
}
{( I nser t I D, sol i d1I D)
( kEdgeSubent Type, 2) };
{( sol i dI D)
( kFaceSubent Type, 1) };
Simple Highlighting Example
Page 83 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
1. Obtain the GS marker for the selected entity from the selection set.
2. Pass the GS marker to the entity class to be converted to a subentity path using the
get Subent Pat hsAt GsMar ker ( ) function. Specify the type of subentity you're interested in (vertex,
edge, face).
3. Once you have the path to the selected subentity, you're ready to call the hi ghl i ght ( ) function,
passing in the correct subentity path.
Topics in this section
Selecting an Entity
Converting GS Markers to Subentity Paths
Highlighting the Subentity
For selection, you'll use a combination of global functions. First, use the acedSSGet ( ) function to obtain
the selection set. Then, use the acedSSNameX( ) function to obtain a subentity GS marker for the
selected entity.
Use the get Subent Pat hsAt GsMar ker ( ) function to obtain the subentity for the GS marker returned by
the acedSSNameX( ) function. The complete syntax for this function is
The first argument to this function is the type of subentity you're interested in (vertex, edge, or face).
In the example code in Highlighting the Subentitythe first call to this function specifies
kEdgeSubent Type because you're going to highlight the corresponding edge. The second call to the
get Subent Pat hsAt GsMar ker ( ) function specifies kFaceSubent Type because you're going to highlight
each face associated with the selected subentity.
The pi ckPoi nt and vi ewXf or marguments are used as additional input for some entities (such as
Selecting an Entity
i nt acedSSGet (
const char * st r ,
const voi d * pt 1,
const voi d * pt 2,
const st r uct r esbuf * f i l t er ,
ads_name ss) ;
i nt acedSSNameX(
st r uct r esbuf ** r bpp,
const ads_name ss,
const l ong i ) ;
Converting GS Markers to Subentity Paths
vi r t ual Acad: : Er r or St at us
AcDbEnt i t y: : get Subent Pat hsAt GsMar ker (
AcDb: : Subent Type t ype,
i nt gsMar k,
const AcGePoi nt 3d& pi ckPoi nt ,
const AcGeMat r i x3d& vi ewXf or m,
i nt & numPat hs,
AcDbFul l Subent Pat h*& subent Pat hs
i nt numI nser t s = 0,
AcDbObj ect I d* ent AndI nser t St ack = NULL) const ;
Page 84 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
mlines) when the GS marker alone does not provide enough information to return the subentity paths.
In the example code in Highlighting the Subentitythey are not used.
The numI nser t s and ent AndI nser t St ack arguments are used for nested inserts. Both the acedNEnt Sel
( ) and acedNEnt Sel P( ) functions return the name of the leaf-level entity, plus a stack of inserts.
Once you've obtained the subentity path to the selected entity, the hardest part of this process is
finished. Now, you need only call the hi ghl i ght ( ) function and pass in the subentity path. If you call
the hi ghl i ght ( ) function without any arguments, the default is to highlight the whole entity.
The following sample code illustrates the steps described for selecting an entity, obtaining a subentity
path, and highlighting different types of subentities associated with a GS marker. This code also
illustrates another useful subentity function:
This function returns a pointer to a copy of the subentity described by the specified path, which can then
be added to the database (as shown in the example).
Note When you are creating new subclasses of AcDbEnt i t y, it is expected that you provide them with
their own implementation of get Subent Pat hsAt GsMar ker ( ) , get GsMar ker sAt Subent Pat h( ) , and
subent Pt r ( ) by overriding the corresponding virtual functions subGet Subent Pat hsAt GsMar ker ( ) ,
subGet GsMar ker sAt Subent Pat h( ) , and subSubent Pt r ( ) , respectively (see Deriving from AcDbEntity).
The hi ghl i ght ( ) function, however, is implemented at the AcDbEnt i t y level and is not generally
expected to be overridden. However, if it is overridden, any new implementation of this function must
call AcDbEnt i t y: : hi ghl i ght ( ) to perform the highlighting.
Highlighting the Subentity
vi r t ual AcDbEnt i t y*
AcDbEnt i t y: : subent Pt r ( const AcDbFul l Subent Pat h& i d) const ;
Page 85 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 get Obj ect AndGsMar ker ( ) t o get t he
/ / obj ect I D of a sol i d and i t s gsmar ker . I t t hen cal l s
/ / hi ghl i ght Edge( ) , hi ghl i ght Faces( ) , and hi ghl i ght Al l ( ) t o
/ / hi ghl i ght t he sel ect ed edge, al l f aces sur r oundi ng t hat
/ / edge, and t hen t he whol e sol i d.
/ /
voi d
hi ghl i ght Test ( )
{
AcDbObj ect I d obj I d;
i nt mar ker ;
i f ( get Obj ect AndGsMar ker ( obj I d, mar ker ) ! = Acad: : eOk)
r et ur n;
hi ghl i ght Edge( obj I d, mar ker ) ;
hi ghl i ght Faces( obj I d, mar ker ) ;
hi ghl i ght Al l ( obj I d) ;
}
/ / Thi s f unct i on uses acedSSGet ( ) t o l et t he user sel ect a
/ / si ngl e ent i t y. I t t hen passes t hi s sel ect i on set t o
/ / acedSSNameX( ) t o get t he gsmar ker . Fi nal l y, t he ent i t y name
/ / i n t he sel ect i on set i s used t o obt ai n t he obj ect I D of
/ / t he sel ect ed ent i t y.
/ /
Acad: : Er r or St at us
get Obj ect AndGsMar ker ( AcDbObj ect I d& obj I d, i nt & mar ker )
{
ads_name sset ;
i f ( acedSSGet ( " _: S" , NULL, NULL, NULL, sset ) ! = RTNORM) {
acut Pr i nt f ( " \ nacedSSGet has f ai l ed" ) ;
r et ur n Acad: : eI nval i dAdsName;
}
/ / Get t he ent i t y f r omt he sel ect i on set and i t s
/ / subent i t y I D. Thi s code assumes t hat t he user
/ / sel ect ed onl y one i t em, a sol i d.
/ /
st r uct r esbuf *pRb;
i f ( acedSSNameX( &pRb, sset , 0) ! = RTNORM) {
acedSSFr ee( sset ) ;
r et ur n Acad: : eAmbi guousOut put ;
}
acedSSFr ee( sset ) ;
/ / Wal k t he l i st t o t he t hi r d i t em, whi ch i s t he sel ect ed
/ / ent i t y' s ent i t y name.
/ /
st r uct r esbuf *pTemp;
i nt i ;
f or ( i =1, pTemp = pRb; i <3; i ++, pTemp = pTemp- >r bnext )
{ ; }
ads_name ename;
ads_name_set ( pTemp- >r esval . r l name, ename) ;
/ / Move on t o t he f our t h l i st el ement , whi ch i s t he gsmar ker .
/ /
pTemp = pTemp- >r bnext ;
mar ker = pTemp- >r esval . r i nt ;
acut Rel Rb( pRb) ;
acdbGet Obj ect I d( obj I d, ename) ;
r et ur n Acad: : eOk;
}
/ / Thi s f unct i on accept s an obj ect I D and a gsmar ker .
/ / The obj ect i s opened, t he gsmar ker i s used t o get t he
/ / AcDbFul l Subent I dPat h, whi ch i s t hen used t o hi ghl i ght
/ / and unhi ghl i ght t he edge used t o sel ect t he obj ect .
/ / Next , t he obj ect ' s subent Pt r ( ) f unct i on i s used t o get
/ / a copy of t he edge. Thi s copy i s t hen added t o t he
/ / dat abase. Fi nal l y, t he obj ect i s cl osed.
/ /
/ / Si nce t he copy of t he subent i t y was added t o t he dat abase
/ / as a new AcDbLi ne ent i t y, i t r emai ns vi si bl e i n t he dr awi ng
/ / edi t or af t er t he command exi t s and wi l l be r epor t ed by t he
/ / Aut oCAD LI ST command.
/ /
voi d
Page 86 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
The example that follows shows highlighting nested block references. As shown in the following figure,
the example creates six entities: three polys (a custom entity) and three boxes. It also creates three
block references (inserts). Insert 3 (i ns3) is an insert of a block that contains pol y3 and box3. Insert 2
(i ns2) is an insert of a block that contains pol y2, box2, and i ns3. Insert 1 (i ns1) is an insert of a block
that contains pol y1, box1, and i ns2.
After the inserts are created, the example highlights the different components.
Highlighting Nested Block References
Page 87 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
voi d
cr eat eI nser t ( )
{
/ / Cr eat e a nest ed i nser t and t r y hi ghl i ght i ng i t s
/ / var i ous subcomponent s.
/ /
/ / Ther e ar e si x ent i t i es i n t ot al - - t hr ee pol ys and
/ / t hr ee boxes ( sol i ds) . We' ve named t hem: pol y1, pol y2,
/ / pol y3, and box1, box2, box3. We al so have t hr ee
/ / i nser t s: i ns1, i ns2, i ns3.
/ /
/ / i ns3 i s an i nser t of a bl ock t hat cont ai ns ( pol y3, box3)
/ / i ns2 i s an i nser t of a bl ock t hat cont ai ns ( pol y2, box2,
/ / i ns3) .
/ / i ns1 i s an i nser t of a bl ock t hat cont ai ns ( pol y1, box1,
/ / i ns2) .
/ /
/ / Let ' s cr eat e t hese ent i t i es f i r st .
/ /
/ / Pol ys
/ /
AsdkPol y *pol y1, *pol y2, *pol y3;
AcGeVect or 3d nor m( 0, 0, 1) ;
i f ( ( pol y1=new AsdkPol y) ==NULL) {
acut Pr i nt f ( " \ nOut of Memor y. " ) ;
r et ur n;
}
i f ( pol y1- >set ( AcGePoi nt 2d( 2, 8) , AcGePoi nt 2d( 4, 8) , 6, nor m,
" POLY1" , 0) ! =Acad: : eOk) {
acut Pr i nt f ( " \ nCannot cr eat e obj ect wi t h gi ven par amet er s. " ) ;
del et e pol y1;
r et ur n;
}
i f ( ( pol y2=new AsdkPol y) ==NULL) {
acut Pr i nt f ( " \ nOut of Memor y. " ) ;
del et e pol y1;
r et ur n;
}
i f ( pol y2- >set ( AcGePoi nt 2d( 7, 8) , AcGePoi nt 2d( 9, 8) , 6, nor m,
" POLY2" , 0) ! =Acad: : eOk) {
acut Pr i nt f ( " \ nCannot cr eat e obj ect wi t h gi ven par amet er s. " ) ;
del et e pol y1;
del et e pol y2;
r et ur n;
}
i f ( ( pol y3=new AsdkPol y) ==NULL) {
acut Pr i nt f ( " \ nOut of Memor y. " ) ;
del et e pol y1;
del et e pol y2;
r et ur n;
}
i f ( pol y3- >set ( AcGePoi nt 2d( 12, 8) , AcGePoi nt 2d( 14, 8) , 6, nor m,
" POLY3" , 0) ! =Acad: : eOk) {
acut Pr i nt f ( " \ nCannot cr eat e obj ect wi t h gi ven par amet er s. " ) ;
del et e pol y1;
del et e pol y2;
del et e pol y3;
r et ur n;
}
post ToDb( pol y1) ;
post ToDb( pol y2) ;
post ToDb( pol y3) ;
/ / Boxes
/ /
AcDb3dSol i d *box1, *box2, *box3;
box1 = new AcDb3dSol i d( ) ;
box2 = new AcDb3dSol i d( ) ;
box3 = new AcDb3dSol i d( ) ;
box1- >cr eat eBox( 2, 2, 2) ;
box2- >cr eat eBox( 2, 2, 2) ;
box3- >cr eat eBox( 2, 2, 2) ;
AcGeMat r i x3d mat ;
Page 88 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Some entities can be exploded, or decomposed, into a set of simpler elements. The specific behavior
depends on the class. For example, boxes can be exploded into regions, then lines. Polylines can be
exploded into line segments. An mtext entity can be exploded into a separate text entity for each line of
the original object. An mline entity can be exploded into individual lines. When you explode a block
reference, AutoCAD copies all entities in the block reference and then splits them into their components.
The expl ode( ) function creates an array of objects derived from AcDbEnt i t y.
The following table shows what happens when you explode each entity, when it is by itself and when it
is in a block insert that is nonuniformly scaled.
Exploding Entities
Exploding entities
Entity By Itself
Nonuniform Scaling (when
in a block)
AcDb3dSolid Regions, bodies NA; can't be exploded
AcDb2dPolyline Lines, arcs Self/NA
AcDb3dPolyline Lines Self
AcDbArc Self Ellipse
AcDbAssocArray Curves (splines, lines, arcs,
circles), blocks, text, and
other standard or custom
objects
NA
AcDbBody Regions, bodies NA
AcDbCircle Self Ellipse
AcDbDimension Solids, lines, text strings,
points
NA
AcDbEllipse Self Self
AcDbLeader Self NA
AcDbLine Self Self
AcDbRay Self Self
AcDbSpline Self Self
AcDbXline Self Self
AcDbFace Self Self
AcDbMline Lines Self
AcDbMText One text entity for each line Self
AcDbPoint Self Self
AcDbPolyFaceMesh AcDbFace Self
AcDbPolygonMesh Self Self
Page 89 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
The expl ode( ) function is a read-only function that does not modify the original entity. It returns a set
of entities for the application to handle as desired. One potential use of this function is to explode a
complex entity to produce simpler entities and then operate on those entities. For example, if you were
implementing an i nt er sect For Poi nt s( ) function for a polyline, it might be easier to deal with the
individual pieces of the polyline rather than the complete entity.
The following statements are true for the EXPLODE command (but not for the expl ode( ) function):
Visual appearance is constant.
The entity being exploded is erased from the database.
One or more new entities are created and appended to the database.
Certain entities also double as objects used for annotation purposes, defined in paper space. The
following objects have annotational support:
Text
MText
Dimenions
Leaders
Balloons
Tolerance
Tables
Blocks
Attributes
Hatches
These objects have the unique property of an annotation scale; custom objects may also use this value.
Annotation scaling maintains visual fidelity across multiple sheets. Based on the annotation scale of a
viewport, a single object might draw itself differently in various viewports. This value is used to ensure
that an annotative object appears the same in mutliple viewports, despite a viewports own scale.
Topics in this section
Functions Unique to Annotative Objects
Object Contexts
AcDbRegion Curves (splines, lines, arcs,
circles)
NA
AcDbShape Self Self
AcDbSolid Self Self
AcDbText Self Self
AcDbTrace Self Self
Annotation Scaling
Page 90 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
In addition to common entity properties and functions, annotation objects have their own functions
implemented through the various classes associated with annotation scaling
(e.g.AcDbAnnot at i veObj ect PE, AcDbPaper Or i ent at i onPE, AcDbAnnot at i onScal e).
Topics in this section
Sample Annotation Object Creation
The code sample below implements many of the significant functions which can be used for annotation
scaling. For further information, please check the ObjectARX Reference Guide.
Functions Unique to Annotative Objects
Sample Annotation Object Creation
Page 91 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm

voi d CAnnot at i onApp: : adskAnnot at i onScal i ngaddAnnoEnt ( )


{
AcGePoi nt 3d i nsPnt ;
/ / pi ck a poi nt on scr een f or t he obj ect
i nt r es = acedGet Poi nt ( NULL, _T( " \ nPi ck poi nt f or obj ect : " ) , asDbl Ar r ay( i nsPnt ) ) ;
/ / i f ok
i f ( r es == RTNORM)
{
Acad: : Er r or St at us es;
/ / l et s car r y out t he pr ocess t o t r y and cr eat e a cust omscal e of 1: 22
/ / f i r st , get t he cur r ent dr awi ng
AcDbDat abase *dwg = cur Doc( ) - >dat abase( ) ;
/ / cr eat e my annot at i on scal e obj ect , may as wel l set i t t o t he cur r ent scal e i n
AcDbAnnot at i onScal e *myAnnot at i onScal e = dwg- >cannoscal e( ) ;
/ / al so cr eat e one on t he st ack so we don' t have t o wor r y about del et i ng i t l at e
AcDbAnnot at i onScal e scal e;
/ / what scal e ar e we set t oo?
AcDbAnnot at i onScal e *cur Scal e = dwg- >cannoscal e( ) ;
AcSt r i ng cur Scal eName;
/ / get t he name of t he scal e
cur Scal e- >get Name( cur Scal eName) ;
/ / i f we ar e not al r eady set t o my 1: 22 scal e t hen we need t o add i t
i f ( _t cscmp( cur Scal eName, _T( " MyScal e 1: 22" ) ) )
{
/ / next get t he obj ect Cont ext Manager
AcDbObj ect Cont ext Manager *cont ext Manager = dwg-
>obj ect Cont ext Manager ( ) ; / / i f ok
i f ( cont ext Manager )
{
/ / now get t he Annot at i on Scal i ng cont ext col l ect i on ( named ACDB_ANNOTATI ONS
AcDbObj ect Cont ext Col l ect i on* const cont ext Col l ect i on = cont ext Manager - >cont e
/ / i f ok
i f ( cont ext Col l ect i on)
{
/ / i f i t doesn' t exi st , t hen l et s set i t up
myAnnot at i onScal e = &scal e;
myAnnot at i onScal e- >set Name( _T( " MyScal e 1: 22" ) ) ;
myAnnot at i onScal e- >set Paper Uni t s( 1) ;
myAnnot at i onScal e- >set Dr awi ngUni t s( 22) ;
/ / l et s check t o see i f we al r eady have t hi s scal e cont ext i n t he cont ext
bool al r eadyHasCont ext = cont ext Col l ect i on- >hasCont ext ( _T( " MyScal e 1: 22" ) )
/ / i f not
i f ( ! al r eadyHasCont ext )
{
/ / add t he new cont ext
es = cont ext Col l ect i on- >addCont ext ( myAnnot at i onScal e) ;
}
/ / now set t he cur r ent dwg annot at i on scal e t o t he newl y cr eat ed scal e con
es = dwg- >set Cannoscal e( myAnnot at i onScal e) ;
}
}
}
/ / next , cr eat e a new i nst ance of my cust omobj ect , t hi s i s der i ved f r omAcDbTex
/ / Annot at i on Cont ext f r amewor k i s al r eady i mpl ement ed f or us
AcDbObj ect Poi nt er <asdkMyAnnot at i veObj ect > ent ;
ent . cr eat e( ) ;
/ / set t he pr oper t i es f or i t
ent - >set Dat abaseDef aul t s( ) ;
ent - >set Posi t i on( i nsPnt ) ;
/ / set t he AcDbText hei ght , because we ar e der i ved f r omAcDbText
/ / t he Annot at i on f r amewor k i s al r eady i n pl ace
ent - >set Hei ght ( 1) ;
ent - >set Text St r i ng( _T( " AcDbText Der i ved Annot at i ve Text - Scal es aut omat i cal l y" )
/ / now set my own Text hei ght , t hi s wi l l show how t o ut i l i se t he Annot at i on
/ / f r amewor k - see t he wor l dDr aw/ vi ewpor t Dr aw of t he cust oment i t y
ent - >set MyText Hei ght ( 1) ;
ent - >set MyText St r i ng( _T( " My Cust omObj ect Text - code i mpl ement ed t o handl e scal
/ / now add t o t he cur r ent space, open i t f or wr i t e
AcDbBl ockTabl eRecor dPoi nt er cur Space( cur Doc( ) - >dat abase( ) - >cur r ent SpaceI d( ) , AcD
/ / i f ok
i f ( cur Space. openSt at us( ) == Acad: : eOk)
Page 92 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Objects derived from the abstract base class AcDbObj ect Cont ext can represent a particular context
which may affect the behavior of objects; in this case, annotation scaling. Applications implement
AcDbObj ect Cont ext Col l ect i on to define custom object contexts; they must also register this
instantiation with AcDbObj ect Cont ext Col l ect i onManager .
Current contexts can be set by invoking AcDbCont ext Col l eci t on: : set Cur r ent Cont ext ( ) . Be sure to
create an AcDbCont ext Col l ect i onI t er at or object to interface with the collection.
This section demonstrates how to create simple AutoCAD entities and add them to the database.
Specifically, it illustrates creating a simple entity, a simple block, a block with attributes, and a block
insert (a block reference). It also shows how to iterate through a block table record.
Topics in this section
Creating a Simple Entity
Creating a Simple Block Table Record
Creating a Block Table Record with Attribute Definitions
Creating a Block Reference with Attributes
Iterating Through a Block Table Record
The following example demonstrates creating a line and appending it to the model space block table
record, as described in Database Primer
Object Contexts
Creating Instances of AutoCAD Entities
Creating a Simple Entity
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;
}
Creating a Simple Block Table Record
Page 93 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
The following example demonstrates creating a new block table record and appending it to the block
table. Then it creates a line and appends it to the new block table record.
An AutoCAD block is a collection of entities that is stored in a block table record. Each block has an
AcDbBl ockBegi n object, followed by one or more AcDbEnt i t y objects, and ends with an AcDbBl ockEnd
object (see the illustration under Entity Ownership).
A block can contain attribute definitions, which are templates for creating attributes. An attribute is
informational text associated with a block. Depending on a user-supplied setting, attribute values may
or may not be copied when a block is inserted into a drawing. Often, the application prompts the user
for the attribute value at runtime.
To create a block table record
1. Create a new block table record.
2. Add the block table record to the block table.
3. Create entities and add them to the block table record.
4. Create attribute definitions, set their values, and add them to the block table record.
When you close the block table record, the block begin and block end objects are added to the block
automatically.
The following example creates a new block table record named
ASDK- BLOCK- WI TH- ATTR and adds it to the block table. Next it creates a circle entity and adds it to the
voi d
makeABl ock( )
{
/ / Cr eat e and name a new bl ock t abl e r ecor d.
/ /
AcDbBl ockTabl eRecor d *pBl ockTabl eRec
= new AcDbBl ockTabl eRecor d( ) ;
pBl ockTabl eRec- >set Name( " ASDK- NO- ATTR" ) ;
/ / Get t he bl ock t abl e.
/ /
AcDbBl ockTabl e *pBl ockTabl e = NULL;
acdbHost Appl i cat i onSer vi ces( ) - >wor ki ngDat abase( )
- >get Symbol Tabl e( pBl ockTabl e, AcDb: : kFor Wr i t e) ;
/ / Add t he new bl ock t abl e r ecor d t o t he bl ock t abl e.
/ /
AcDbObj ect I d bl ockTabl eRecor dI d;
pBl ockTabl e- >add( bl ockTabl eRecor dI d, pBl ockTabl eRec) ;
pBl ockTabl e- >cl ose( ) ;
/ / Cr eat e and add a l i ne ent i t y t o t he component ' s
/ / bl ock r ecor d.
/ /
AcDbLi ne *pLi ne = new AcDbLi ne( ) ;
AcDbObj ect I d l i neI d;
pLi ne- >set St ar t Poi nt ( AcGePoi nt 3d( 3, 3, 0) ) ;
pLi ne- >set EndPoi nt ( AcGePoi nt 3d( 6, 6, 0) ) ;
pLi ne- >set Col or I ndex( 3) ;
pBl ockTabl eRec- >appendAcDbEnt i t y( l i neI d, pLi ne) ;
pLi ne- >cl ose( ) ;
pBl ockTabl eRec- >cl ose( ) ;
}
Creating a Block Table Record with Attribute Definitions
Page 94 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
new block table record. It creates two attribute definition entities (the second is a clone of the first) and
appends them to the same block table record
Page 95 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
voi d
def i neBl ockWi t hAt t r i but es(
AcDbObj ect I d& bl ockI d, / / Thi s i s a r et ur ned val ue.
const AcGePoi nt 3d& basePoi nt ,
doubl e t ext Hei ght ,
doubl e t ext Angl e)
{
i nt r et Code = 0;
AcDbBl ockTabl e *pBl ockTabl e = NULL;
AcDbBl ockTabl eRecor d* pBl ockRecor d = new AcDbBl ockTabl eRecor d;
AcDbObj ect I d ent i t yI d;
/ / St ep 1: Set t he bl ock name and base poi nt of t he
/ / bl ock def i ni t i on.
/ /
pBl ockRecor d- >set Name( " ASDK- BLOCK- WI TH- ATTR" ) ;
pBl ockRecor d- >set Or i gi n( basePoi nt ) ;
/ / Open t he bl ock t abl e f or wr i t e.
/ /
acdbHost Appl i cat i onSer vi ces( ) - >wor ki ngDat abase( )
- >get Symbol Tabl e( pBl ockTabl e, AcDb: : kFor Wr i t e) ;
/ / St ep 2: Add t he bl ock t abl e r ecor d t o bl ock t abl e.
/ /
pBl ockTabl e- >add( bl ockI d, pBl ockRecor d) ;
/ / St ep 3: Cr eat e a ci r cl e ent i t y.
/ /
AcDbCi r cl e *pCi r cl e = new AcDbCi r cl e;
pCi r cl e- >set Cent er ( basePoi nt ) ;
pCi r cl e- >set Radi us( t ext Hei ght * 4. 0) ;
pCi r cl e- >set Col or I ndex( 3) ;
/ / Append t he ci r cl e ent i t y t o t he bl ock r ecor d.
/ /
pBl ockRecor d- >appendAcDbEnt i t y( ent i t yI d, pCi r cl e) ;
pCi r cl e- >cl ose( ) ;
/ / St ep 4: Cr eat e an at t r i but e def i ni t i on ent i t y.
/ /
AcDbAt t r i but eDef i ni t i on *pAt t def
= new AcDbAt t r i but eDef i ni t i on;
/ / Set t he at t r i but e def i ni t i on val ues.
/ /
pAt t def - >set Posi t i on( basePoi nt ) ;
pAt t def - >set Hei ght ( t ext Hei ght ) ;
pAt t def - >set Rot at i on( t ext Angl e) ;
/ / For hor i zont al modes ot her t han AcDb: : kText Lef t
/ / and ver t i cal modes ot her t han AcDb: : kText Base,
/ / you may need t o cal l set Al i gnment Poi nt ( ) . See t he
/ / AcDbText : : set Al i gnment Poi nt ( ) document at i on f or det ai l s.
pAt t def - >set Hor i zont al Mode( AcDb: : kText Lef t ) ;
pAt t def - >set Ver t i cal Mode( AcDb: : kText Base) ;
pAt t def - >set Pr ompt ( " Pr ompt " ) ;
pAt t def - >set Text St r i ng( " DEFAULT" ) ;
pAt t def - >set Tag( " Tag" ) ;
pAt t def - >set I nvi si bl e( Adesk: : kFal se) ;
pAt t def - >set Ver i f i abl e( Adesk: : kFal se) ;
pAt t def - >set Pr eset ( Adesk: : kFal se) ;
pAt t def - >set Const ant ( Adesk: : kFal se) ;
pAt t def - >set Fi el dLengt h( 25) ;
/ / Append t he at t r i but e def i ni t i on t o t he bl ock.
/ /
pBl ockRecor d- >appendAcDbEnt i t y( ent i t yI d, pAt t def ) ;
/ / The second at t r i but e def i ni t i on i s a l i t t l e easi er
/ / because we ar e cl oni ng t he f i r st one.
/ /
AcDbAt t r i but eDef i ni t i on *pAt t def 2
= AcDbAt t r i but eDef i ni t i on: : cast ( pAt t def - >cl one( ) ) ;
/ / Set t he val ues t hat ar e speci f i c t o t he
/ / second at t r i but e def i ni t i on.
/ /
AcGePoi nt 3d t empPt ( basePoi nt ) ;
t empPt . y - = pAt t def 2- >hei ght ( ) ;
pAt t def 2- >set Posi t i on( t empPt ) ;
pAt t def 2- >set Col or I ndex( 1) ; / / Red
pAt t def 2- >set Const ant ( Adesk: : kTr ue) ;
Page 96 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
A block reference is an entity that references a block table record. It contains an insertion point, ECS
information, X,Y,Z scale factors, rotation, and a normal vector (parameters for viewing the block in its
new location). When you insert a block into a drawing, AutoCAD conserves memory by creating a block
reference rather than copying the block itself into the drawing.
If you insert a block with attribute definitions, the attribute values can be filled in by the user at runtime
or by the application when the block is inserted.
To insert a block with attributes into a drawing
1. Create a block reference entity (AcDbBl ockRef er ence).
2. Call the set Bl ockTabl eRecor d( ) function to specify the object ID of the referenced block table
record. (The object ID can also be specified directly in the constructor of the block reference.)
3. Append the block reference to a block table record (model space, paper space, or some other block).
4. Use a block table record iterator on the referenced block table record, searching for attribute
definitions. For each one found, create a new AcDbAt t r i but e entity, fill it in with the attribute
definition's data, and then append it to the block reference using the appendAt t r i but e( ) function.
The following example creates a block reference, fills in the attributes, and appends the reference to the
database. It uses global functions to obtain user input. The def i neBl ockWi t hAt t r i but es( ) function
shown in the previous section is used to create the block reference. This example uses a block table
record iterator to step through the attribute definitions and create a corresponding attribute for each
attribute definition. The attribute values are set from the original attribute definition using the
set Pr oper t i esFr om( ) function.
Creating a Block Reference with Attributes
Page 97 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
voi d
addBl ockWi t hAt t r i but es( )
{
/ / Get an i nser t i on poi nt f or t he bl ock r ef er ence,
/ / def i ni t i on, and at t r i but e def i ni t i on.
/ /
AcGePoi nt 3d basePoi nt ;
i f ( acedGet Poi nt ( NULL, " \ nEnt er i nser t i on poi nt : " ,
asDbl Ar r ay( basePoi nt ) ) ! = RTNORM)
r et ur n;
/ / Get t he r ot at i on angl e f or t he at t r i but e def i ni t i on.
/ /
doubl e t ext Angl e;
i f ( acedGet Angl e( asDbl Ar r ay( basePoi nt ) ,
" \ nEnt er r ot at i on angl e: " , &t ext Angl e) ! = RTNORM)
r et ur n;
/ / Def i ne t he hei ght used f or t he at t r i but e def i ni t i on t ext .
/ /
doubl e t ext Hei ght ;
i f ( acedGet Di st ( asDbl Ar r ay( basePoi nt ) ,
" \ nEnt er t ext hei ght : " , &t ext Hei ght ) ! = RTNORM)
r et ur n;
/ / Bui l d t he bl ock def i ni t i on t o be i nser t ed.
/ /
AcDbObj ect I d bl ockI d;
def i neBl ockWi t hAt t r i but es( bl ockI d, basePoi nt ,
t ext Hei ght , t ext Angl e) ;
/ / St ep 1: Al l ocat e a bl ock r ef er ence obj ect .
/ /
AcDbBl ockRef er ence *pBl kRef = new AcDbBl ockRef er ence;
/ / St ep 2: Set up t he bl ock r ef er ence t o t he newl y
/ / cr eat ed bl ock def i ni t i on.
/ /
pBl kRef - >set Bl ockTabl eRecor d( bl ockI d) ;
/ / Gi ve i t t he cur r ent UCS nor mal .
/ /
st r uct r esbuf t o, f r om;
f r om. r est ype = RTSHORT;
f r om. r esval . r i nt = 1; / / UCS
t o. r est ype = RTSHORT;
t o. r esval . r i nt = 0; / / WCS
AcGeVect or 3d nor mal ( 0. 0, 0. 0, 1. 0) ;
acedTr ans( &( nor mal . x) , &f r om, &t o, Adesk: : kTr ue,
&( nor mal . x) ) ;
/ / Set t he i nser t i on poi nt f or t he bl ock r ef er ence.
/ /
pBl kRef - >set Posi t i on( basePoi nt ) ;
/ / I ndi cat e t he LCS 0. 0 angl e, not necessar i l y t he UCS 0. 0 angl e.
/ /
pBl kRef - >set Rot at i on( 0. 0) ;
pBl kRef - >set Nor mal ( nor mal ) ;
/ / St ep 3: Open t he cur r ent dat abase' s model space
/ / bl ock t abl e r ecor d.
/ /
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( ) ;
/ / Append t he bl ock r ef er ence t o t he model space
/ / bl ock t abl e r ecor d.
/ /
AcDbObj ect I d newEnt I d;
pBl ockTabl eRecor d- >appendAcDbEnt i t y( newEnt I d, pBl kRef ) ;
pBl ockTabl eRecor d- >cl ose( ) ;
/ / St ep 4: Open t he bl ock def i ni t i on f or r ead.
/ /
AcDbBl ockTabl eRecor d *pBl ockDef ;
acdbOpenObj ect ( pBl ockDef , bl ockI d, AcDb: : kFor Read) ;
/ / Set up a bl ock t abl e r ecor d i t er at or t o i t er at e
Page 98 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
The following example demonstrates how to iterate through the elements in a block table record and
print out the elements.
The pr i nt Al l ( ) function opens the block table for reading, and then it opens the block name supplied
by the user. A new iterator steps through the block table records. If the record contains an entity, the
iterator prints a message about the entity.
Iterating Through a Block Table Record
voi d
pr i nt Al l ( )
{
i nt r c;
char bl kName[ 50] ;
r c = acedGet St r i ng( Adesk: : kTr ue,
" Ent er Bl ock Name <CR f or cur r ent space>: " ,
bl kName) ;
i f ( r c ! = RTNORM)
r et ur n;
i f ( bl kName[ 0] == ' \ 0' ) {
i f ( acdbHost Appl i cat i onSer vi ces( ) - >wor ki ngDat abase( )
- >t i l emode( ) == Adesk: : kFal se) {
st r uct r esbuf r b;
acedGet Var ( " cvpor t " , &r b) ;
i f ( r b. r esval . r i nt == 1) {
st r cpy( bl kName, ACDB_PAPER_SPACE) ;
} el se {
st r cpy( bl kName, ACDB_MODEL_SPACE) ;
}
} el se {
st r cpy( bl kName, ACDB_MODEL_SPACE) ;
}
}
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 ( bl kName, pBl ockTabl eRecor d,
AcDb: : kFor Read) ;
pBl ockTabl e- >cl ose( ) ;
AcDbBl ockTabl eRecor dI t er at or *pBl ockI t er at or ;
pBl ockTabl eRecor d- >newI t er at or ( pBl ockI t er at or ) ;
f or ( ; ! pBl ockI t er at or - >done( ) ;
pBl ockI t er at or - >st ep( ) )
{
AcDbEnt i t y *pEnt i t y;
pBl ockI t er at or - >get Ent i t y( pEnt i t y, AcDb: : kFor Read) ;
AcDbHandl e obj Handl e;
pEnt i t y- >get AcDbHandl e( obj Handl e) ;
char handl eSt r [ 20] ;
obj Handl e. get I nt oAsci i Buf f er ( handl eSt r ) ;
const char *pCname = pEnt i t y- >i sA( ) - >name( ) ;
acut Pr i nt f ( " Obj ect I d %l x, handl e %s, cl ass %s. \ n" ,
pEnt i t y- >obj ect I d( ) , handl eSt r , pCname) ;
pEnt i t y- >cl ose( ) ;
}
del et e pBl ockI t er at or ;
pBl ockTabl eRecor d- >cl ose( ) ;
acut Pr i nt f ( " \ n" ) ;
}
Complex Entities
Page 99 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
This section provides examples showing how to create and iterate through complex entities. Complex
entities and their subentities are listed in the Entities Definedsection.
Topics in this section
Creating a Complex Entity
Iterating Through Vertices in a Polyline
Deleting Complex Entities
This example shows how to create an AcDb2dPol yl i ne object and set some of its propertieslayer,
color index, the closed parameter. It then creates four vertex objects (AcDb2dPol yl i neVer t ex), sets
their location, and appends them to the polyline object. Finally, it closes all the open objectsvertices,
polyline, block table record, and block table. When the polyline object is closed, AutoCAD adds the
AcDbSequenceEnd object to it automatically.
Creating a Complex Entity
voi d
cr eat ePol yl i ne( )
{
/ / Set f our ver t ex l ocat i ons f or t he pl i ne.
/ /
AcGePoi nt 3dAr r ay pt Ar r ;
pt Ar r . set Logi cal Lengt h( 4) ;
f or ( i nt i = 0; i < 4; i ++) {
pt Ar r [ i ] . set ( ( doubl e) ( i / 2) , ( doubl e) ( i %2) , 0. 0) ;
}
/ / Dynami cal l y al l ocat e an AcDb2dPol yl i ne obj ect ,
/ / gi ven f our ver t ex el ement s whose l ocat i ons ar e suppl i ed
/ / i n pt Ar r . The pol yl i ne has no el evat i on, and i s
/ / expl i ci t l y set as cl osed. The pol yl i ne i s si mpl e;
/ / t hat i s, not cur ve f i t or a spl i ne. By def aul t , t he
/ / wi dt hs ar e al l 0. 0 and t her e ar e no bul ge f act or s.
/ /
AcDb2dPol yl i ne *pNewPl i ne = new AcDb2dPol yl i ne(
AcDb: : k2dSi mpl ePol y, pt Ar r , 0. 0, Adesk: : kTr ue) ;
pNewPl i ne- >set Col or I ndex( 3) ;
/ / Get a poi nt er t o a bl ock t abl e obj ect .
/ /
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) ;
/ / Get a poi nt er t o t he MODEL_SPACE Bl ockTabl eRecor d.
/ /
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( ) ;
/ / Append t he pl i ne obj ect t o t he dat abase and
/ / obt ai n i t s obj ect I D.
/ /
AcDbObj ect I d pl i neObj I d;
pBl ockTabl eRecor d- >appendAcDbEnt i t y( pl i neObj I d,
pNewPl i ne) ;
pBl ockTabl eRecor d- >cl ose( ) ;
/ / Make t he pl i ne obj ect r esi de on l ayer " 0" .
/ /
pNewPl i ne- >set Layer ( " 0" ) ;
pNewPl i ne- >cl ose( ) ;
}
Page 100 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
The following example shows iterating through the vertices in a polyline using a vertex iterator. It then
prints the coordinates for each vertex.
If an application deletes a complex entity that is not database resident, the application is responsible for
also deleting all the subentities associated with that complex entity.
Complex entities and their subentities are listed in the Entities Definedsection. Complex entities that are
not database resident do not include an AcDbSequenceEnd object.
The following example shows how to delete the subentities of an AcDb2dPolyline:
Iterating Through Vertices in a Polyline
/ / Accept s t he obj ect I D of an AcDb2dPol yl i ne, opens i t , and get s
/ / a ver t ex i t er at or . I t t hen i t er at es t hr ough t he ver t i ces,
/ / pr i nt i ng out t he ver t ex l ocat i on.
/ /
voi d
i t er at e( AcDbObj ect I d pl i neI d)
{
AcDb2dPol yl i ne *pPl i ne;
acdbOpenObj ect ( pPl i ne, pl i neI d, AcDb: : kFor Read) ;
AcDbObj ect I t er at or *pVer t I t er = pPl i ne- >ver t exI t er at or ( ) ;
pPl i ne- >cl ose( ) ; / / Fi ni shed wi t h t he pl i ne header .
AcDb2dVer t ex *pVer t ex;
AcGePoi nt 3d l ocat i on;
AcDbObj ect I d ver t exObj I d;
f or ( i nt ver t exNumber = 0; ! pVer t I t er - >done( ) ;
ver t exNumber ++, pVer t I t er - >st ep( ) )
{
ver t exObj I d = pVer t I t er - >obj ect I d( ) ;
acdbOpenObj ect ( pVer t ex, ver t exObj I d,
AcDb: : kFor Read) ;
l ocat i on = pVer t ex- >posi t i on( ) ;
pVer t ex- >cl ose( ) ;
acut Pr i nt f ( " \ nVer t ex #%d' s l ocat i on i s"
" : %0. 3f , %0. 3f , %0. 3f " , ver t exNumber ,
l ocat i on[ X] , l ocat i on[ Y] , l ocat i on[ Z] ) ;
}
del et e pVer t I t er ;
}
Deleting Complex Entities
voi d del et e2dPol y( AcDb2dPol yl i ne* pPl i ne)
{
AcDbObj ect I t er at or * pI t er =pPl i ne- >ver t exI t er at or ( ) ;
AcDbEnt i t y* pEnt ;
f or ( ; ! pI t er - >done( ) ; )
{
pEnt =pI t er - >ent i t y( ) ;
/ / Must st ep t he i t er at or f i r st so t hat i t i s no l onger
/ / si t t i ng on t he ent i t y t hat ' s about t o be del et ed.
pI t er - >st ep( ) ;
del et e pEnt ;
}
del et e pI t er ;
del et e pPl i ne;
}
Page 101 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Entity functions retrieve and set coordinate values using World Coordinate System values. The only
exception to this rule is the AcDb2dPol yl i neVer t ex class, described later in this section, which uses
Entity Coordinate System (ECS) values. For example, if you call the get Cent er ( ) function on a circle,
AutoCAD returns the X,Y center of the circle in world coordinates.
Topics in this section
Entity Coordinate System
AcDb2dVertex Class
If you define your own entity, it may be useful to store its geometric constructs (points, angles, and
vectors) in terms of its own relative coordinate system. For example, arcs establish a coordinate system
in which the Z axis is perpendicular to the plane of the arc. An arc's center point is returned in world
coordinates, but the start and end angles can only be interpreted with respect to its ECS. In such cases,
implement the get Ecs( ) function to return a matrix that is used to transform the entity from its Entity
Coordinate System to the World Coordinate System. If an entity is not defined in terms of its own Entity
Coordinate System, then the get Ecs( ) function returns the identity matrix. (In other words, any time
an entity's get Ecs( ) function returns the identity matrix, you can assume the entity is defined in terms
of world coordinates.)
In AutoCAD, planar entities have an ECS; 3D entities do not. AutoCAD entities that can return a
nonidentity matrix for their get Ecs( ) function are:
Dimensions
Text
Circles
Arcs
2D polylines
Block inserts
Points
Traces
Solids
Shapes
Attribute definitions
Attributes
An AcDb2dPol yl i ne has as an elevation and a series of X,Y points of class AcDb2dVer t ex. The posi t i on
( ) and set Posi t i on( ) functions of AcDb2dVer t ex specify 3D locations in the ECS. The Z coordinate
passed in to the set Posi t i on( ) function is stored in the entity and is returned by the posi t i on( )
Coordinate System Access
Entity Coordinate System
AcDb2dVertex Class
Page 102 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
function, but is otherwise ignored. It does not affect the polyline's elevation.
The AcDb2dPol yl i ne class provides the ver t exPosi t i on( ) function, which returns a World Coordinate
System value for the vertex passed in. The only way to change the elevation of a polyline is using the
AcDb2dPol yl i ne: : set El evat i on( ) function.
The abstract base class AcDbCur ve provides a number of functions for operating on curves, including
functions for projecting, extending, and offsetting curves, as well as a set of functions for querying
curve parameters. Curves can be defined either in parameter space or in Cartesian coordinate space. A
3D curve is a function of one parameter (f(t)), while a 3D surface is a function of two parameters (f
(u,v)). Conversion functions allow you to convert data from its parameter representation to points in the
Cartesian coordinate system. Splines, for example, are best represented in parameter space. To split a
spline into three equal parts, you first find the parameters that correspond to the points of the spline
and then operate on the spline in parameter space. Curves can be used as trim boundaries, extension
boundaries, and as construction objects for creating complex 3D entities.
You can project a curve onto a plane in a given direction, as shown in the following example.
Curve Functions
/ / Accept s an el l i pse obj ect I D, opens t he el l i pse, and uses
/ / i t s get Or t hoPr oj ect edCur ve member f unct i on t o cr eat e a
/ / new el l i pse t hat i s t he r esul t of a pr oj ect i on ont o t he
/ / pl ane wi t h nor mal <1, 1, 1>. The r esul t i ng el l i pse i s
/ / added t o t he model space bl ock t abl e r ecor d.
/ /
voi d
pr oj ect El l i pse( AcDbObj ect I d el l i pseI d)
{
AcDbEl l i pse *pEl l i pse;
acdbOpenObj ect ( pEl l i pse, el l i pseI d, AcDb: : kFor Read) ;
/ / Now pr oj ect t he el l i pse ont o a pl ane wi t h a
/ / nor mal of <1, 1, 1>.
/ /
AcDbEl l i pse *pPr oj ect edCur ve;
pEl l i pse- >get Or t hoPr oj ect edCur ve( AcGePl ane(
AcGePoi nt 3d: : kOr i gi n, AcGeVect or 3d( 1, 1, 1) ) ,
( AcDbCur ve*&) pPr oj ect edCur ve) ;
pEl l i pse- >cl ose( ) ;
AcDbObj ect I d newCur veI d;
addToModel Space( newCur veI d, pPr oj ect edCur ve) ;
}
/ / Accept s an el l i pse obj ect I D, opens t he el l i pse, and uses
/ / i t s get Of f set Cur ves( ) member f unct i on t o cr eat e a new
/ / el l i pse t hat i s of f set 0. 5 dr awi ng uni t s f r omt he
/ / or i gi nal el l i pse.
/ /
voi d
of f set El l i pse( AcDbObj ect I d el l i pseI d)
{
AcDbEl l i pse *pEl l i pse;
acdbOpenObj ect ( pEl l i pse, el l i pseI d, AcDb: : kFor Read) ;
/ / Now gener at e an el l i pse of f set by 0. 5 dr awi ng uni t s.
/ /
AcDbVoi dPt r Ar r ay cur ves;
pEl l i pse- >get Of f set Cur ves( 0. 5, cur ves) ;
pEl l i pse- >cl ose( ) ;
AcDbObj ect I d newCur veI d;
addToModel Space( newCur veI d, ( AcDbEnt i t y*) cur ves[ 0] ) ;
}
Associating Hyperlinks with Entities
Page 103 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
ObjectARX

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

database operations: symbol tables,


dictionaries, groups, and xrecords. As part of any drawing, AutoCAD creates a fixed set of symbol tables
and the named object dictionary, which contains two other dictionaries, the MLINE style and GROUP
dictionaries. The section examples demonstrate how to add entries to symbol tables, dictionaries, and
groups, and how to query the contents of these containers using iterators. They also show how to create
and use your own dictionaries and xrecords to manage application data and objects. For a description of
the extension dictionary of an AcDbObj ect object, see Database Objects.
Topics in this section
Comparison of Symbol Tables and Dictionaries
Symbol Tables
Dictionaries
Layouts
Xrecords
Symbol tables and dictionaries perform essentially the same function; they contain entries that are
database objects that can be looked up using a text string key. You can add entries to these container
objects, and you can use an iterator to step through the entries and query their contents.
The AutoCAD database always contains a fixed set of nine symbol tables, described in the following
section. You cannot create or delete a symbol table, but you can add or change the entries in a symbol
table, which are called records. Each symbol table contains only a particular type of object. For
example, the AcDbLayer Tabl e contains only objects of type AcDbLayer Tabl eRecor d. Symbol tables are
defined in this manner mainly for compatibility with AutoCAD Release 12 and previous releases of
AutoCAD.
Dictionaries provide a similar mechanism for storing and retrieving objects with associated name keys.
The AutoCAD database creates the named object dictionary whenever it creates a new drawing. The
named object dictionary can be viewed as the master table of contents for the nonentity object
structures in a drawing. This dictionary, by default, contains nine dictionaries: the GROUP dictionary,
the MLINE style dictionary, the layout dictionary, the plot style name dictionary, the color dictionary, the
material dictionary, the plot settings dictionary, the table style dictionary, and the SYSVAR dictionary.
You can create any number of additional objects and add them to the named object dictionary.
However, the best practice is to add one object directly to the named object dictionary and have that
object in turn own the other objects associated with your application. Typically, the owning object is a
container class such as a dictionary. Use your assigned four-letter Registered Developer Symbol for the
name of this class.
An AcDbDi ct i onar y object can contain any type of AcDbObj ect , including other dictionaries. A
dictionary object does not perform type checking of entries. However, the MLINE style dictionary should
contain only instances of class AcDbMl i neSt yl e, and the GROUP dictionary should contain only
instances of AcDbGr oup. An application may require specific typing for entries in a dictionary that it
creates and maintains.
The class hierarchy for symbol tables, symbol table records, dictionaries, and iterators is as follows.
Container Objects
Comparison of Symbol Tables and Dictionaries
Page 106 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
An important difference between symbol tables and dictionaries is that symbol table records cannot be
erased directly by an ObjectARX

application. These records can be erased only with the PURGE


command or selectively filtered out with wblock operations. Objects owned by a dictionary can be
erased.
Warning Erasing dictionaries or dictionary entries (see Essential Database Objects) probably will cause
AutoCAD or other applications to fail.
Another important difference is that symbol table records store their associated look-up name in a field
in their class definition. Dictionaries, on the other hand, store the name key as part of the dictionary,
independent of the object it is associated with, as shown in the following figure.
Symbol Tables
Page 107 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Names used in symbol table records and in dictionaries must follow these rules:
Names can be any length in ObjectARX, but symbol names entered by users in AutoCAD are limited
to 255 characters.
AutoCAD preserves the case of names but does not use the case in comparisons. For example,
AutoCAD considers Floor to be the same symbol as FLOOR.
Names can be composed of all characters allowed in Windows NT filenames, except comma (,),
backquote (), semi-colon (;), and equal sign (=).
The AutoCAD database contains the following symbol tables (parentheses indicate class name and
AutoCAD command used for adding entries):
Block table (AcDbBl ockTabl e; BLOCK)
Layer table (AcDbLayer Tabl e; LAYER)
Text style table (AcDbText St yl eTabl e; STYLE)
Linetype table (AcDbLi net ypeTabl e; LTYPE)
View table (AcDbVi ewTabl e; VIEW)
UCS table (AcDbUCSTabl e; UCS)
Viewport table (AcDbVi ewpor t Tabl e; VPORT)
Registered applications table (AcDbRegAppTabl e)
Dimension styles table (AcDbDi mSt yl eTabl e; DIMSTYLE)
Each table contains objects of a corresponding subclass of AcDbSymbol Tabl eRecor d.
Each symbol table class provides a get At ( ) function for looking up the record specified by name. The
signatures for overloaded forms of the get At ( ) function are as follows. (##BASE_NAME## stands for any
of the nine symbol table class types.)
or
This first version of this function returns a pointer to the opened record in pRecor d if a matching record
is found and the open operation (with the specified mode) succeeds. If openEr asedRecor d is true, the
function returns the object even if it was erased. If openEr asedRecor d is false, the function returns a
NULL pointer and an error status of eWasEr ased for erased objects.
The second version of the get At ( ) function returns the AcDbObj ect I d of the record specified by name
in the value r ecor dI d if a matching record is found. If get Er asedRecor d is true, the function returns
the matching object even if it has been erased. The object is not opened.
Once you have obtained a record and opened it, you can get and set different member values. For the
specific symbol table record class for a complete list of the class member functions, see the ObjectARX
Reference.
Other important functions provided by all symbol table classes are the has( ) and add( ) functions. See
the example in Creating and Modifying a Layer Table Record. The signatures for the has( ) function are
Acad: : Er r or St at us
AcDb##BASE_NAME##Tabl e: : get At ( const char * pEnt r yName,
AcDb##BASE_NAME##Tabl eRecor d*& pRecor d,
AcDb: : OpenMode mode,
bool openEr asedRecor d = f al se) const ;
Acad: : Er r or St at us
AcDb##BASE_NAME##Tabl e: : get At ( const char * pEnt r yName,
AcDbObj ect I d& r ecor dI d,
bool get Er asedRecor d = f al se) const ;
Page 108 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
The has( ) function returns true if the table contains a record with a name that matches pName or i d.
The add( ) function has the following signatures:
This function adds the record pointed to by pRecor d to both the database containing the table and the
table itself. If the additions succeed and the r ecor dI d argument is non-NULL, it is set to the
AcDbObj ect I d of the record in the database.
Topics in this section
Block Table
Layer Table
Iterators
Entities in the database typically belong to a block table record. The block table contains three records
by default, *MODEL_SPACE, *PAPER_SPACE, and *PAPER_SPACE0, which correspond to the three initial
drawing spaces that can be edited directly by AutoCAD users. For examples of adding entities to the
model space block table record, see Database Primer, and Entities.
The *PAPER_SPACE and *PAPER_SPACE0 records correspond to the two predefined paper space layouts
in AutoCAD. You can add, modify, and delete paper space layouts.
New block table records are created when the user issues a BLOCK command or an INSERT command to
insert an external drawing. New block table records are also created with the acdbEnt Make( ) function.
The BLOCK? command lists the contents of the block table, with the exception of the *MODEL_SPACE
and *PAPER_SPACE records. See Entities, for examples of block table record and block reference
creation. (A block reference is an entity that refers to a given block table record.)
The layer table contains one layer, layer 0, by default. A user adds layers to this table with the LAYER
command.
Topics in this section
Layer Properties
Creating and Modifying a Layer Table Record
bool
AcDb##BASE_NAME##Tabl e: : has( const char * pName) const ;
bool
AcDb##BASE_NAME##Tabl e: : has( AcDbObj ect I d i d) const ;
Acad: : Er r or St at us
AcDb##BASE_NAME##Tabl e: : add( AcDb##BASE_NAME##Tabl eRecor d*
pRecor d) ;
Acad: : Er r or St at us
AcDb##BASE_NAME##Tabl e: : add( AcDbObj ect I d& r ecor dI d,
AcDb##BASE_NAME##Tabl eRecor d* pRecor d) ;
Block Table
Layer Table
Page 109 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
The AcDbLayer Tabl eRecor d class contains member functions for specifying a number of layer properties
that affect the display of their associated entities. All entities must refer to a valid layer table record.
The AutoCAD User's Guide provides a detailed description of layer properties.
The following sections list the member functions for setting and querying layer properties.
Frozen/Thawed
When a layer is frozen, graphics are not regenerated.
On/Off
When a layer is OFF, graphics are not displayed.
Viewport
This set VPDFLT( ) function specifies whether the layer by default is visible or invisible in new viewports.
Locked/Unlocked
Entities on a locked layer cannot be modified by an AutoCAD user or opened for the wr i t e( ) function
within a program.
Color
The color set by the set Col or ( ) function is used when an entity's color is BYLAYER.
Layer Properties
Acad: : Er r or St at us
AcDbLayer Tabl eRecor d: : set I sFr ozen( bool f r ozen) ;
bool
AcDbLayer Tabl eRecor d: : i sFr ozen( ) const ;
voi d AcDbLayer Tabl eRecor d: : set I sOf f ( bool of f ) ;
bool
AcDbLayer Tabl eRecor d: : i sOf f ( ) const ;
voi d AcDbLayer Tabl eRecor d: : set VPDFLT( bool f r ozen) ;
bool
AcDbLayer Tabl eRecor d: : VPDFLT( ) const ;
voi d AcDbLayer Tabl eRecor d: : set I sLocked( bool l ocked) ;
bool
AcDbLayer Tabl eRecor d: : i sLocked( ) const ;
voi d AcDbLayer Tabl eRecor d: : set Col or ( const AcCmCol or & col or ) ;
AcCmCol or
AcDbLayer Tabl eRecor d: : col or ( ) const ;
Page 110 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Linetype
The linetype set by the set Li net ypeObj ect I d( ) function is used when an entity's linetype is BYLAYER.
The following example shows obtaining the layer table for the current database and opening it for
writing. It creates a new layer table record (AcDbLayer Tabl eRecor d) and sets certain attributes of the
layer (name, frozen attribute, on/off, viewport, and locked). Then it creates a color class object and sets
the color of the layer to red.
To set the linetype for the layer, this example opens the linetype table for reading and obtains the
object ID of the linetype record for the desired linetype (here, DASHED). Once it has the object ID for
the linetype, it closes the linetype table and sets the linetype for the new layer table record. This
example uses the add( ) function to add the layer table record to the layer table. Finally, it closes the
layer table record and the layer table itself.
voi d AcDbLayer Tabl eRecor d: : set Li net ypeObj ect I d( AcDbObj ect I d i d) ;
AcDbObj ect I d
AcDbLayer Tabl eRecor d: : l i net ypeObj ect I d( ) const ;
Creating and Modifying a Layer Table Record
Page 111 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Each symbol table has a corresponding iterator that you can create with the
AcDb##BASE_NAME##Tabl e: : newI t er at or ( ) function.
The newI t er at or ( ) function creates an object that can be used to step through the contents of the
table and sets pI t er at or to point to the iterator object. If at Begi nni ng is true, the iterator starts at
the beginning of the table; if false, it starts at the end of the table. If the ski pEr ased argument is true,
the iterator is positioned initially at the first (or last) unerased record; if false, it is positioned at the first
(or last) record, regardless of whether it has been erased. For a description of the functions available for
each iterator class, see the ObjectARX Reference.
voi d
addLayer ( )
{
AcDbLayer Tabl e *pLayer Tbl ;
acdbHost Appl i cat i onSer vi ces( ) - >wor ki ngDat abase( )
- >get Symbol Tabl e( pLayer Tbl , AcDb: : kFor Wr i t e) ;
i f ( ! pLayer Tbl - >has( " ASDK_TESTLAYER" ) ) {
AcDbLayer Tabl eRecor d *pLayer Tbl Rcd
= new AcDbLayer Tabl eRecor d;
pLayer Tbl Rcd- >set Name( " ASDK_TESTLAYER" ) ;
pLayer Tbl Rcd- >set I sFr ozen( 0) ; / / l ayer t o THAWED
pLayer Tbl Rcd- >set I sOf f ( 0) ; / / l ayer t o ON
pLayer Tbl Rcd- >set VPDFLT( 0) ; / / vi ewpor t def aul t
pLayer Tbl Rcd- >set I sLocked( 0) ; / / un- l ocked
AcCmCol or col or ;
col or . set Col or I ndex( 1) ; / / set col or t o r ed
pLayer Tbl Rcd- >set Col or ( col or ) ;
/ / For l i net ype, we need t o pr ovi de t he obj ect I D of
/ / t he l i net ype r ecor d f or t he l i net ype we want t o
/ / use. Fi r st , we need t o get t he obj ect I D.
/ /
AcDbLi net ypeTabl e *pLi net ypeTbl ;
AcDbObj ect I d l t I d;
acdbHost Appl i cat i onSer vi ces( ) - >wor ki ngDat abase( )
- >get Symbol Tabl e( pLi net ypeTbl , AcDb: : kFor Read) ;
i f ( ( pLi net ypeTbl - >get At ( " DASHED" , l t I d) )
! = Acad: : eOk)
{
acut Pr i nt f ( " \ nUnabl e t o f i nd DASHED"
" l i net ype. Usi ng CONTI NUOUS" ) ;
/ / CONTI NUOUS i s i n ever y dr awi ng, so use i t .
/ /
pLi net ypeTbl - >get At ( " CONTI NUOUS" , l t I d) ;
}
pLi net ypeTbl - >cl ose( ) ;
pLayer Tbl Rcd- >set Li net ypeObj ect I d( l t I d) ;
pLayer Tbl - >add( pLayer Tbl Rcd) ;
pLayer Tbl Rcd- >cl ose( ) ;
pLayer Tbl - >cl ose( ) ;
} el se {
pLayer Tbl - >cl ose( ) ;
acut Pr i nt f ( " \ nl ayer al r eady exi st s" ) ;
}
}
Iterators
Acad: : Er r or St at us
AcDb##BASE_NAME##Tabl e: : newI t er at or (
AcDb##BASE_NAME##Tabl eI t er at or *& pI t er at or ,
bool at Begi nni ng = Adesk: : kTr ue,
bool ski pEr ased = Adesk: : kTr ue) const ;
Page 112 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
When you create a new iterator, you are also responsible for deleting it. A symbol table should not be
closed until all of the iterators it has constructed have been deleted.
In addition to the symbol tables, the block table record has an iterator that operates on the entities it
owns. The AcDbBl ockTabl eRecor d class returns an object of class AcDbBl ockTabl eRecor dI t er at or
when you ask it for a new iterator. This iterator enables you to step through the entities contained in
the block table record and to seek particular entities.
Note It is essential the iterator is deleted after use. Any non-deleted operator will cause an assert when
the database is closed. Pass a reference to the pointer through acdbFr ee( ) , or implement your own
del et e( ) methods.
Topics in this section
Iterating over Tables
The code in the following example creates an iterator that walks through the symbol table records in the
linetype table. It obtains each record, opens it for read, obtains the linetype name, closes the record,
and then prints the linetype name. At the end, the program deletes the iterator.
To create a new dictionary, you need to create an instance of AcDbDi ct i onar y, add it to the database,
and register it with its owner object. Use the setAt function to add objects to the dictionary and the
database.
The set At ( ) function adds a new entry specified by newVal ue to the dictionary. If the entry already
exists, it is replaced by the new value. The name of the object is specified by sr chKey. The object ID of
the entry is returned in r et Obj I d.
Iterating over Tables
voi d
i t er at eLi net ypes( )
{
AcDbLi net ypeTabl e *pLi net ypeTbl ;
acdbHost Appl i cat i onSer vi ces( ) - >wor ki ngDat abase( )
- >get Symbol Tabl e( pLi net ypeTbl , AcDb: : kFor Read) ;
/ / Cr eat e a new i t er at or t hat st ar t s at t abl e
/ / begi nni ng and ski ps del et ed.
/ /
AcDbLi net ypeTabl eI t er at or *pLt I t er at or ;
pLi net ypeTbl - >newI t er at or ( pLt I t er at or ) ;
/ / Wal k t he t abl e, get t i ng ever y t abl e r ecor d and
/ / pr i nt i ng t he l i net ype name.
/ /
AcDbLi net ypeTabl eRecor d *pLt Tabl eRcd;
char *pLt Name;
f or ( ; ! pLt I t er at or - >done( ) ; pLt I t er at or - >st ep( ) ) {
pLt I t er at or - >get Recor d( pLt Tabl eRcd, AcDb: : kFor Read) ;
pLt Tabl eRcd- >get Name( pLt Name) ;
pLt Tabl eRcd- >cl ose( ) ;
acut Pr i nt f ( " \ nLi net ype name i s: %s" , pLt Name) ;
f r ee( pLt Name) ;
}
del et e pLt I t er at or ;
pLi net ypeTbl - >cl ose( ) ;
}
Dictionaries
Page 113 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
When you add an entry to a dictionary, the dictionary automatically attaches a reactor to the entry. If
the object is erased, the dictionary is notified and removes it from the dictionary.
Topics in this section
Groups and the Group Dictionary
MLINE Style Dictionary
Layout Dictionary
Creating a Dictionary
Iterating over Dictionary Entries
A group is a container object that maintains an ordered collection of database entities. Groups can be
thought of as named persistent selection sets. They do not have an ownership link to the entities they
contain.
When an entity is erased, it is automatically removed from the groups that contain it. If an entity is
unerased, it is automatically reinserted into the group.
Use the AcDbGr oup: : newI t er at or ( ) function to obtain an iterator and step through the entities in the
group. The AcDbGr oup class also provides functions for appending and prepending entities to the group,
inserting entities at a particular index in the group, removing entities, and transferring entities from one
position in the group to another. See AcDbGroup in the ObjectARX Reference.
You can also assign properties to all members of a group using the set Col or ( ) , set Layer ( ) ,
set Li net ype( ) , set Vi si bi l i t y( ) , and set Hi ghl i ght ( ) functions of the AcDbGr oup class. These
operations have the same effect as opening each entity in the group and setting its property directly.
Groups should always be stored in the GROUP dictionary, which can be obtained as follows:
An alternative way to obtain the GROUP dictionary is to look up ACAD_GROUP in the named object
dictionary.
The following functions are part of an application that first prompts the user to select some entities that
are placed into a group called ASDK_GROUPTEST. Then it calls the function r emoveAl l But Li nes( ) to
iterate over the group and remove all the entities that are not lines. Finally, it changes the remaining
entities in the group to red.
Groups and the Group Dictionary
AcDbDi ct i onar y* pGr pDi ct =
acdbHost Appl i cat i onSer vi ces( ) - >wor ki ng Dat abase( ) - >
get Gr oupDi ct i onar y( pGr oupDi ct , AcDb: : kFor Wr i t e) ;
Page 114 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
voi d
gr oups( )
{
AcDbGr oup *pGr oup = new AcDbGr oup( " gr oupt est " ) ;
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 gr oupI d;
pGr oupDi ct - >set At ( " ASDK_GROUPTEST" , pGr oup, gr oupI d) ;
pGr oupDi ct - >cl ose( ) ;
pGr oup- >cl ose( ) ;
makeGr oup( gr oupI d) ;
r emoveAl l But Li nes( gr oupI d) ;
}
/ / Pr ompt s t he user t o sel ect obj ect s t o add t o t he gr oup,
/ / opens t he gr oup i dent i f i ed by " gr oupI d" passed i n as
/ / an ar gument , t hen adds t he sel ect ed obj ect s t o t he gr oup.
/ /
voi d
makeGr oup( AcDbObj ect I d gr oupI d)
{
ads_name sset ;
i nt er r = acedSSGet ( NULL, NULL, NULL, NULL, sset ) ;
i f ( er r ! = RTNORM) {
r et ur n;
}
AcDbGr oup *pGr oup;
acdbOpenObj ect ( pGr oup, gr oupI d, AcDb: : kFor Wr i t e) ;
/ / Tr aver se t he sel ect i on set , exchangi ng each ads_name
/ / f or an obj ect I D, t hen addi ng t he obj ect t o t he gr oup.
/ /
l ong i , l engt h;
ads_name ename;
AcDbObj ect I d ent I d;
acedSSLengt h( sset , &l engt h) ;
f or ( i = 0; i < l engt h; i ++) {
acedSSName( sset , i , ename) ;
acdbGet Obj ect I d( ent I d, ename) ;
pGr oup- >append( ent I d) ;
}
pGr oup- >cl ose( ) ;
acedSSFr ee( sset ) ;
}
/ / Accept s an obj ect I D of an AcDbGr oup obj ect , opens i t ,
/ / t hen i t er at es over t he gr oup, r emovi ng al l ent i t i es t hat
/ / ar e not AcDbLi nes and changi ng al l r emai ni ng ent i t i es i n
/ / t he gr oup t o col or r ed.
/ /
voi d
r emoveAl l But Li nes( AcDbObj ect I d gr oupI d)
{
AcDbGr oup *pGr oup;
acdbOpenObj ect ( pGr oup, gr oupI d, AcDb: : kFor Wr i t e) ;
AcDbGr oupI t er at or *pI t er = pGr oup- >newI t er at or ( ) ;
AcDbObj ect *pObj ;
f or ( ; ! pI t er - >done( ) ; pI t er - >next ( ) ) {
pI t er - >get Obj ect ( pObj , AcDb: : kFor Read) ;
/ / I f i t i s not a l i ne or descended f r oma l i ne,
/ / cl ose i t and r emove i t f r omt he gr oup. Ot her wi se,
/ / j ust cl ose i t .
/ /
i f ( ! pObj - >i sKi ndOf ( AcDbLi ne: : desc( ) ) ) {
/ / AcDbGr oup: : r emove( ) r equi r es t hat t he obj ect
/ / t o be r emoved be cl osed, so cl ose i t now.
/ /
pObj - >cl ose( ) ;
pGr oup- >r emove( pI t er - >obj ect I d( ) ) ;
} el se {
pObj - >cl ose( ) ;
}
}
del et e pI t er ;
Page 115 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
Note The pointer for AcDbGr oup cannot be closed until all of its iterators have been deleted.
The MLINE style dictionary contains objects of class AcDbMl i neSt yl e. As shown in the following figure,
objects of class AcDbMl i ne each have an associated MLINE style that specifies the properties of the
multiline, such as offset, color, and linetype.
The layout dictionary is a default dictionary within the named object dictionary that contains objects of
class AcDbLayout . The AcDbLayout object stores the characteristics of a paper space layout, including
the plot settings. Each AcDbLayout object also contains an object ID of an associated block table record,
which stores the entities associated with the layout.
The following example creates a new dictionary (ASDK_DICT) and adds it to the named object
dictionary. Then it creates two new objects of the custom class AsdkMyCl ass (derived from AcDbObj ect )
and adds them to the dictionary using the set At ( ) function.
Note You need to close the objects after adding them with the set At ( ) function.
MLINE Style Dictionary
Layout Dictionary
Creating a Dictionary
Page 116 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
The iterator class for dictionaries is AcDbDi ct i onar yI t er at or . The following code excerpt obtains a
dictionary (ASDK_DICT) from the named object dictionary. It then uses a dictionary iterator to step
through the dictionary entries and print the value of the stored integer. Finally, it deletes the iterator
and closes the dictionary.
/ / Thi s f unct i on cr eat es t wo obj ect s of cl ass AsdkMyCl ass.
/ / I t f i l l s t hemi n wi t h t he i nt eger s 1 and 2, and t hen adds
/ / t hemt o t he di ct i onar y associ at ed wi t h t he key ASDK_DI CT. I f t hi s
/ / di ct i onar y doesn' t exi st , i t i s cr eat ed and added t o t he named
/ / obj ect di ct i onar y.
/ /
voi d
cr eat eDi ct i onar y( )
{
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 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 , cr eat e i t and add
/ / i t t o t he named obj ect di ct i onar y.
/ /
AcDbDi ct i onar y *pDi ct ;
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( ) ;
i f ( pDi ct ) {
/ / Cr eat e new obj ect s t o add t o t he new di ct i onar y,
/ / add t hem, t hen cl ose t hem.
/ /
AsdkMyCl ass *pObj 1 = new AsdkMyCl ass( 1) ;
AsdkMyCl ass *pObj 2 = new AsdkMyCl ass( 2) ;
AcDbObj ect I d r I d1, r I d2;
pDi ct - >set At ( " OBJ 1" , pObj 1, r I d1) ;
pDi ct - >set At ( " OBJ 2" , pObj 2, r I d2) ;
pObj 1- >cl ose( ) ;
pObj 2- >cl ose( ) ;
pDi ct - >cl ose( ) ;
}
}
Iterating over Dictionary Entries
Page 117 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
AutoCAD initially contains three layouts: a model space layout and two paper space layouts. These
layouts can be accessed by tabs at the bottom of the drawing window in AutoCAD. The tabs are initially
named Model, Layout1, and Layout2.
The Model tab is the default tab and represents model space, in which you generally create your
drawing. The Layout1 and Layout2 tabs represent paper space and are generally used for laying out
your drawing for printing. The paper space layouts display a paper image that shows the printable
boundary for the configured print device.
It is recommended that you use paper space layouts for preparing final drawings for output, but printing
can be performed from any layout, including the model space layout. For more information on using
layouts in AutoCAD, see the AutoCAD User's Guide.
Topics in this section
Layout Class Overview
The main classes involved in creating and manipulating layouts are the following:
AcDbLayout class
AcDbPlotSettings class
AcDbPlotSettingsValidator class
voi d
i t er at eDi ct i onar y( )
{
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 a poi nt er t o t he ASDK_DI CT di ct i onar y.
/ /
AcDbDi ct i onar y *pDi ct ;
pNamedobj - >get At ( " ASDK_DI CT" , ( AcDbObj ect *&) pDi ct ,
AcDb: : kFor Read) ;
pNamedobj - >cl ose( ) ;
/ / Get an i t er at or f or t he ASDK_DI CT di ct i onar y.
/ /
AcDbDi ct i onar yI t er at or * pDi ct I t er = pDi ct - >newI t er at or ( ) ;
AsdkMyCl ass *pMyCl ;
Adesk: : I nt 16 val ;
f or ( ; ! pDi ct I t er - >done( ) ; pDi ct I t er - >next ( ) ) {
/ / Get t he cur r ent r ecor d, open i t f or r ead, and
/ / pr i nt i t s dat a.
/ /
pDi ct I t er - >get Obj ect ( ( AcDbObj ect *&) pMyCl ,
AcDb: : kFor Read) ;
pMyCl - >get Dat a( val ) ;
pMyCl - >cl ose( ) ;
acut Pr i nt f ( " \ ni nt val i s: %d" , val ) ;
}
del et e pDi ct I t er ;
pDi ct - >cl ose( ) ;
}
Layouts
Layout Class Overview
Page 118 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
AcDbLayoutManager class
AcApLayoutManager class
AcDbLayoutManagerReactor class
AcDbLayout , AcDbPl ot Set t i ngs, and AcDbPl ot Set t i ngsVal i dat or are used to create and set
attributes on layout objects. AcDbLayout Manager , AcApLayout Manager , and
AcDbLayout Manager React or are used to manipulate layout objects and to perform other layout-related
tasks.
Topics in this section
Layout Objects
The Layout Manager
Information about layouts is stored in instances of the AcDbLayout class. A layout object contains the
printing and plotting settings information needed to print the desired portion of the drawing. For
example, a layout object contains the plot device, media size, plot area, and plot rotation, as well as
several other attributes that help define the area to be printed.
AcDbLayout objects are stored in the ACAD_LAYOUT dictionary within the named object dictionary of
the database. There is one AcDbLayout object per paper space layout, as well as a single AcDbLayout
for model space. Each AcDbLayout object contains the object ID of its associated
AcDbBl ockTabl eRecor d. This makes it easy to find the block table record in which the layout's actual
geometry resides. If an AcDbBl ockTabl eRecor d represents a layout, then it contains the object ID of its
associated AcDbLayout object.
Most of the plot information for layout objects is stored in AcDbPl ot Set t i ngs, the base class of
AcDbLayout . You can create named plot settings and use them to initialize other AcDbLayout objects.
This allows you to export and import plot settings from one layout to another. These named plot
settings are stored in instances of the AcDbPl ot Set t i ngs class. There is one AcDbPl ot Set t i ngs object
for each named plot setting and they are stored in the ACAD_PLOTSETTINGS dictionary within the
named object dictionary.
Note There is no direct connection between AcDbLayout objects in the ACAD_LAYOUT dictionary and
AcDbPl ot Set t i ngs objects in the ACAD_PLOTSETTINGS dictionary.
You can manage AcDbLayout objects by using the AcApLayout Manager class. The AcApLayout Manager
class allows you to
Create layouts
Delete layouts
Rename layouts
Copy and clone layouts
Set the current layout
Find a particular layout
Set the plot characteristics of a layout
Layout Objects
The Layout Manager
Page 119 of 123 ObjectARX Introductory Concepts
7/7/2014 file:///C:/Users/ike/AppData/Local/Temp/~hh25F4.htm
There is one instance of a layout manager per application. The layout manager always operates on the
current layout.
Xrecords enable you to add arbitrary, application-specific data. Because they are an alternative to
defining your own object class, they are especially useful to AutoLISP

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