Class 2 - AutoCAD's Database
This minimun data is represented basically by objects like layers, linetypes, text styles, etc. Due that you have layer 0, stadard text style, continuous linetype and others.
How data is stored
This Database mantains all sort of objects a drawing needs to exist. These objects are stored into appropriate containers which are special objects made to manage objects of the same type. This way we have appropriate methods and procedures to store entities, layers, text styles, etc.
Each object stored into Database receives an identifier that is called ObjectId. This identifier is unique inside the same AutoCAD session and it is valid during the lifecycle of each object. The ObjectId is generated by its Database and you don't need to worry about how to create it.
Inside ObjectARX we have basically 3 kind of objects:
- Entities: Objects with graphical representation (lines, arcs, texts, ...);
- Containers: Special objects to store and manage collections (layer table, linetype table, ...);
- Objects: Objects without any graphical representation (groups, layouts, ...).
AutoCAD's Database structure
Creating objects
To create an object through ObjectARX we have some kind of recipe depending on what type of object it is and where we would like to store it (most of time we need to store an objects inside its specific container). Basically, you will follow this sequence:
- Declare a pointer to the object type you would like to create and call its new operator;
- With this pointer, call appropriate methods of this object to change its features;
- Get a pointer to the Database where you would like to create the object (most of time the current Database);
- Open the appropriate container where it should be stored;
- Call the specific container method to store your object passing its pointer;
- Receive its ObjectId automatically generated by its container;
- Finish the operation closing all opened objects including containers and the object you have just created.
Obviously you will create some handy classes to allow the automation of this processes because they are very similar and can be easily reused. The main idea is to create a sort of database utility funcions like: AddLayer, AddLine, AddCircle, AddTextStyle, etc.
* It is very important to not forget to close opened objects because this will cause AutoCAD to terminate.
Sample code to create a line (AcDbLine)
This code demonstrates how to create a simple line between two points. The process is simple and no error check is made. This code needs to be embedded inside an ObjectARX application structure to work. The main idea is to show you the concepts. Further we will create a working code. Pay attention to the order of opening and closing operations.
// We first need to declare a couple of points
AcGePoint3d startPt(1.0, 1.0, 0.0);
AcGePoint3d endPt(10.0, 10.0, 0.0);
// Now we need to instantiate an AcDbLine pointer
// In this case, its constructor allows me to pass the 2 points
AcDbLine *pLine = new AcDbLine(startPt, endPt);
// Now we need to open the appropriate container which is inside BlockTable
AcDbBlockTable *pBlockTable = NULL;
// First, get the current database and then get the BlockTable
AcDbDatabase* pDB = acdbHostApplicationServices()->workingDatabase();
pDB->getSymbolTable(pBlockTable, AcDb::kForRead);
// Inside BlockTable, open the ModelSpace
AcDbBlockTableRecord* pBlockTableRecord = NULL;
pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord, AcDb::kForWrite);
// After get ModelSpace we can close the BlockTable
pBlockTable->close();
// Using ModelSpace pointer we can add our brand new line
AcDbObjectId lineId = AcDbObjectId::kNull;
pBlockTableRecord->appendAcDbEntity(lineId, pLine);
// To finish the process we need to close ModelSpace and the entity
pBlockTableRecord->close();
pLine->close();
On the next class we will present the ObjectARX application structure and will build and compile a simple application using the above code. See you there!




31 Comments:
Hello,
Should I delete the AcDbEntity pointer?
By
Anonymous, at 6:07 PM
Why you don't close the AcDbDatabase pointer?
By
Anonymous, at 6:09 PM
Hi there!
1)You only should delete those pointers you have allocate but not added to database. Once you have add an object to database AutoCAD take control of its lifecycle and you only need to close it.
2)The AcDbDatabase pointer is managed by AutoCAD and it stay opened as long as its associated drawing is available. You should only delete AcDbDatabase pointer when you have allocate it and it is not attached to any opened document inside AutoCAD application environment.
By
Fernando Malard, at 7:29 PM
Hi Fernando,
Here is what I did base on your code sample.
// ----- lesqsimpleLine._MyLine command (do not rename)
static void lesqsimpleLine_MyLine(void)
{
acutPrintf("\nSimple Line Command in ObjectARX...");
int iRet;
AcGePoint3d startPt, endPt;
iRet = acedGetPoint(NULL , "\nFrom point:" , asDblArray(startPt) );
if (iRet == RTNORM)
{
iRet = acedGetPoint(asDblArray(startPt) , "\nTo point: " , asDblArray(endPt) );
if (iRet == RTNORM)
{
AcDbLine *pLine = new AcDbLine(startPt, endPt);
AcDbBlockTable *pBlockTable = NULL;
AcDbDatabase* pDB = acdbHostApplicationServices()->workingDatabase();
pDB->getSymbolTable(pBlockTable, AcDb::kForRead);
AcDbBlockTableRecord* pBlockTableRecord = NULL;
pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord, AcDb::kForWrite);
pBlockTable->close();
AcDbObjectId lineId = AcDbObjectId::kNull;
pBlockTableRecord->appendAcDbEntity(lineId, pLine);
pBlockTableRecord->close();
pLine->close();
}
else { acutPrintf("\nNo second point selected..."); }
}
else { acutPrintf("\nNo first point selected..."); }
By
Anonymous, at 5:49 PM
Hi,
I did not test your code but it looks good.
Keep improving!
BTW, I will request those users who would like to submit their improved samples and post into a user files folder.
Regards,
Fernando.
By
Fernando Malard, at 5:59 PM
Great,
Just let me know where that folder is going to be please.
Gracias,
Luis.
By
Anonymous, at 6:10 PM
Hi Fernando & Luis,
There are code fragements designed by you two in this section. Can anybody tell me which environment this code fit? is it a Visual C++ one?
Best Regards,
Yang
By
Anonymous, at 10:46 AM
Hi Yang,
Yes, these code fragments are in C++ targeting ObjectARX 2004 and above.
You need to use VC++.NET 2002 to create ObjectARX applications compatible with AutoCAD 2004, 2005 and 2006.
Regards,
Fernando
By
Fernando Malard, at 7:10 PM
is there any vc++ with objectarx free study material.
By
Rebekh, at 8:02 AM
Hello Rebekh,
Major ObjectARX contents on the Internet are placed into Forum Groups and Blogs. There are a couple of books about ObjectARX at Amazon.com
Only free sources I known is my Blog and Kean's Blog (http://through-the-interface.typepad.com/). VC++ information can be found at Microsoft MSDN website.
Hope this helps.
Regards.
By
Fernando Malard, at 8:17 AM
Thank u for ur help.
By
Rebekh, at 10:19 AM
Hello,
I build your Program in studio.net
I obtain the following error
"fatal error C1083: Cannot open include file: 'arxHeaders.h': No such file or directory "
how cain i Proceed?
By
RadhaKrishna, at 4:50 PM
Hello,
I build your Program in studio.net
I obtain the following error
"fatal error C1083: Cannot open include file: 'arxHeaders.h': No such file or directory "
how cain i Proceed?
By
RadhaKrishna, at 4:51 PM
Hi,
Take a look at Class3a. You need to setup VS to know both \inc and \lib ObjectARX paths.
Regards,
Fernando.
By
Fernando Malard, at 5:37 PM
Hello
How can I acess, add or modify from program, entries made in Drawing Properties... on the Custom tab?
Regards
By
Anonymous, at 9:40 AM
Hi,
There is a class to handle that. It is called AcDbDatabaseSummaryInfo and its pointer can be acquired with acdbGetSummaryInfo() global function.
If you need to access the same information from outside AutoCAD, there is an ActiveX control called DwgPropsX. Inside this control you will find several methods to put/get information.
Regards,
Fernando.
By
Fernando Malard, at 10:51 AM
Hello
I have a class derived from AcDbDoubleClickEdit, and I have a class derived from AcDbEntity.
I use ...desc()->addX(AcDbDoubleClickEdit::desc() ... to add the double click reactor to the entity.
My goal is to modify some entity-s internal data in the database when the user double clicks on a specific entity.
But I can't open them in write mode, i get error eLockViolation .
Is there any way to overcome this obstacle?
Regards, Alonso
By
Alonso, at 7:42 AM
Hi Alonso,
If you are using AutoCAD 2007 the double click API is now part of CUI. Take a look at the .NET class:
Autodesk.AutoCAD.Customization.DoubleClickAction
If you are not using 2007, try to put the following code just before you open the entity for write:
AcApDocument *pDoc=acDocManager->curDocument();
acDocManager->lockDocument(pDoc,AcAp::kWrite);
After close the entity, unlock the document like this:
acDocManager->unlockDocument(pDoc);
Hope this help.
Regards.
By
Fernando Malard, at 9:06 AM
Hello
Thx for the help, it really solved my problem.
Grateful, Alonso
By
Alonso, at 4:31 AM
Hello
I have an arx application and a custom menu wrote for AutoCAD 2006.
How can I load the custom menu from the application, without telling the user to use the AutoCAD command CUI?
Can you give me an example how to use DEMANDLOAD to set my arx application to load whenever AutoCAD starts?
I'm aiming to make an install kit for my program where I set everything, so the user simply starts AutoCAD and can use my menu and program.
Regards, Alonso
By
Alonso, at 5:52 AM
Hi Alonso,
The AutoCAD MENU and TOOLBARS can be manipulated directly through the COM API or through C# (.NET API). There is a sample at:
C:\ObjectARX 2007\samples\dotNet\CuiSamp
It shows how to create menus, toolbars, etc., using the .NET CUI API through C# (the same works if you use VB.NET).
Regarding to the demand loading process it is just a matter of registry entries. You can find more information about this on the ObjectARX SDK Help into "Demand Loading" topic.
Regards,
Fernando.
By
Fernando Malard, at 8:20 AM
please send simple code of vb to integrete autocad database
to get the parameter of line
By
sandip, at 7:13 AM
Hello Fernando,
I have a question:
[code]
AcDbObjectId lineId=AcDbObjectId::kNull;
pBlockTableRecord->appendAcDbEntity(lineId,pLine);
[/code]
Why don't you use function: appendAcDbEntity(pLine) ??
Regards,
Duy
By
Duy, at 6:37 PM
Hi Duy,
In fact you are right but I prefer to use this other signature version which returns the new entity's objectId because would be a good idea to check if it is valid.
I have removed a lot of code check on these samples to provide a clear code and an easy understanding.
It is really up to you to choose the right signature to use.
Regards,
Fernando.
By
Fernando Malard, at 10:16 PM
Dear Fernando,
Please how to determine if DB pointer is still valid.
In my case I have two DWG for example dwg1 and dwg2 when close dwg2 the pointer is invalid after close document so case terminate of program.
So what is the solution?
Is the solution using Reactor? Please give me any code sample if answer is yes?
Best Regards,
M.S
By
Anonymous, at 10:44 AM
Hi M.S,
It is not a good idea to keep the pointers of databases. The best approach is to monitor the documents through a document reactor and then get each document attached database pointer.
Take a look at the docman sample of ObjectARX SDK.
Regards,
Fernando.
By
Fernando Malard, at 10:56 AM
Dear Fernando,
I have this code it work but when replace activateDocument with setCurDocument at line 12 and 16 this code does not work (Terminate program)
(This code activate second dwg if first dwg is active and vise versa)
AcDbVoidPtrArray *m_pDBArray = acdbActiveDatabaseArray();
if(m_pDBArray->length() == 2)
{
AcDbDatabase *pDb1 = (AcDbDatabase *)(m_pDBArray->at(0));
AcDbDatabase *pDb2 = (AcDbDatabase *)(m_pDBArray->at(1));
AcApDocument *pDoc0;
AcApDocManager *doc_manager = acDocManagerPtr();
pDoc0 = doc_manager->curDocument();
AcDbDatabase *pDbTemp0 = pDoc0->database();
If(pDbTemp0 == pDb1)
{
AcApDocument *pDoc;
pDoc = doc_manager->document(pDb2);
Acad::ErrorStatus error11= doc_manager->activateDocument(pDoc);
}
else if(pDbTemp0 == pDb2)
{
AcApDocument *pDoc;
pDoc = doc_manager->document(pDb1);
Acad::ErrorStatus error11= doc_manager->activateDocument(pDoc);
}
}
else
{
acutPrintf("\n Number of DWG less than 2");
}
Do you have any idea?
Regards,
M.S
By
Anonymous, at 3:06 AM
Hi M.S,
Activate a document and make a document current are not the same thing. I would recommend you to read the ObjectARX documentation on the MDI section which explains in details what each concept is.
There are some restrictions that are valid to activate a document and others to set a document current.
Regards,
Fernando.
By
Fernando Malard, at 10:38 AM
Hi,
I have plane AutoCad 2008 and AutoCad Map 2009 on the same machine.
Arx's with the line
AcDbDatabase* pDB = acdbHostApplicationServices()->workingDatabase();
can not be loaded in 2008 "cannot find a procedure that it needs"
but well in Map
Any idea's?
By
Jelena, at 10:51 AM
Hi Jelena,
Really strange.
All 2009 based products should be binary compatible with 2008 compiled ObjectARX applications.
Did you test with a simple empty project created with ARXWizard?
Regards,
By
Fernando Malard, at 10:57 AM
Hi Fernando,
Empty project made with ArxWizard works fine. Although, other arx projects not involving the line with
"acdbHostApplicationServices()->workingDatabase();"
are also working fine (like your MinimumApp).
Temporary it’s no problem since I can work with Map.
I'll post if I find something on this matter.
By
Jelena, at 11:16 AM
Post a Comment
<< Home