In my personal opinion, the greatest feature of ObjectARX is the capability to develop your own objects and entities. This powerful feature will allow you to create complex applications and provide your users a unique experience using your software.
This feature is possible since ObjectARX beginning (officially at AutoCAD R13). Since Autodesk provided this feature, its own developers thought that they could develop their selves vertical solutions for the most interesting market areas. At that time, products like MAP, MCAD and ADT start to show up.
Today there are several vertical products based on AutoCAD made by Autodesk and much more developed by third-party companies.
How is this possible?
ObjectARX takes full advantage of C++ language features like inheritance, polymorphism and overriding among many others. This allows Autodesk to publish part of AutoCAD source code using a SDK like package with library and header files.
Beyond this point, ObjectARX exports some classes allowing you to derive from them and implement your own behavior taking advantage of all ready-to-use methods and overriding those ones you need.
This way, when your custom class is defined and implemented your application will be compiled and linked with AutoCAD native libraries and headers and will be possible to load your module (DLL) at runtime to use your own objects inside AutoCAD! Great hum?
When to use and when not to use custom objects
Even being a powerful feature of ObjectARX, custom objects are not the best solution for any kind of implementation. Sometimes is better to user another solution like XData or XRecords. This will totally depend on how much complex your application is and how much complex will be the way users will interact with your product.
You need to be sure when to use or not custom classes inside ObjectARX. Personally I perform some questions to myself that will help me to decide:
- My product's elements are simple or complex?
- My elements are only complex in terms of non-graphical data or they will require complex graphical representation?
- Do I need to protect my element's data when the drawing is out of my company?
- Will my elements present a complex interaction with users very different from AutoCAD native entities?
- Do I need to share common information among my elements?
These questions will really help you to decide or not to user custom classes.
How to use a custom objects?
The first step is to choose your base class. This will depend on what type of custom object are you willing to implement. Basically you need to choose if it will represent an entity or a data object. If it will be an entity you will need to derive it from AcDbEntity or other of its derived classes. In other hand, if it will not have graphical appearance, you will derive it from AcDbObject. There are some ObjectARX classes that does not allow you to derive from. Take a look at ObjectARX documentation for a complete list.
It is very important to you clearly understand these differences between AcDbEntity and AcDbObject. Remember that every AcDbEntity if also an AcDbObject but NOT ALL AcDbObject is an AcDbEntity. This is because AcDbEntity is derived from AcDbObject.
I really would like you to walk through the ObjectARX class hierarchy to locate yourself in that tree and see clearly what are we talking about. There is a DWG file, called classmap.dwg, inside your ObjectARX SDK folder called \classmap.
Runtime Identification
AutoCAD requires that every custom class has its own runtime type identification. This will be used by AutoCAD and by your own application. Basically you don't need to care about this because there are MACROS to do this job for you. The AcRxObject class is the responsible to perform this feature and exactly due that it is on the top of AcRx tree.
The runtime identification is made by some functions like the following:
- desc(), a static member function that returns the class descriptor object of a particular (known) class.
- cast(), a static member function that returns an object of the specified type, or NULL if the object is not of the required class (or a derived class).
- isKindOf() returns whether an object belongs to the specified class (or a derived class).
- isA() returns the class descriptor object of an object whose class is unknown.
To declare these functions you will need to use the following MACRO inside your class declaration:
ACRX_DECLARE_MEMBERS(CLASS_NAME);
To implement these functions, you will need to use one of the following MACROS:
- ACRX_NO_CONS_DEFINE_MEMBERS (CLASS_NAME, PARENT_CLASS):
Use for abstract classes and any other classes that should not be instantiated.
- ACRX_CONS_DEFINE_MEMBERS (CLASS_NAME, PARENT_CLASS, VERNO):
Use for transient classes that can be instantiated but are not written to file.
- ACRX_DXF_DEFINE_MEMBERS (CLASS_NAME,PARENT_CLASS, DWG_VERSION, MAINTENANCE_VERSION, PROXY_FLAGS, DXF_NAME, APP):
Use for classes that can be written to, or read from, DWG and DXF files.
// Inside kInitAppMsg function handler
MyClass::rxInit();
// Call this only once for all of your custom classes
acrxBuildClassHierarchy();
// Inside kUnloadAppMsg function handler
deleteAcRxClass(MyClass::desc());
This will guarantee that when your application is loaded AutoCAD recognizes your class and when it was not present (unloaded) AutoCAD will transform your class instances into Proxy entities. Proxy entities are a binary package that protects and preserves your custom object during DWG roundtrip without your application.