Welcome to my ObjectARX Blog.
I have decided to create this Blog to allow AutoCAD advanced users and AutoLISP / VBA programmers to get into ObjectARX world.
As it is a very complex environment I will try to be brief and clear on my explanations and present it step by step.
Hope you enjoy!
56 comments :
Hi fernando,
cannot download the course examples.Web site asks for
login.
Bom fin de semana,
Karlheinz (Germany)
Hello Fernando !
congratulations for that good practice oriented tutorial.
i did not seen nothing equal in the library-shops that can not explain it good, like you do.
regards
Nuno (Germany)
Hi
I have a heave drawing that take several munites to open. it has somebody else objectARX objects. I want to open the 2D part of each entity. is there a way to do it using objectARX programming?
Thanks
maged
Hi maged,
First, if this drawing contains third-party entities you will need at least its DBX enabler to allow you to see the correct shape and functionality of those entities.
To be able to access custom entity information you will be limited to the last level of a known ObjectARX class depending on from what class the custom entity was derived.
Suppose that the custom entity has been derived from AcDbEntity. If you have the DBX enabler loaded you will be able to acess information at AcDbEntity level.
How to tranform those entities into 2D is very generic regarding to a custom entity because you will need to know what this entity does and how it was implemented.
If you have access to the company who created these custom entities you may try to request the .H (header) files and respective .LIB (library files) for this object. This will allow you to recognize them inside your application. This is exactly what Autodesk does with ObjectARX. Autodesk provides the .H and .LIB files allowing us to interact with native entities and access its properties.
Regards,
Fernando.
Hi Fernando,
I can not appload the "hello world" arx example. I built the "step01" as in the examples of "ObjectARX" manual. when I tried to appload "Step01.arx" using "appload" in autoCAD there was an error: " unable to load the step01.arx file". Any help
Thanks
Maged Choucair
Hi Maged,
This can occur due several reasons. You may check the following:
-Are you compiling your application with an ObjectARX version incompatible with version of AutoCAD? Ex.: Compile with 2000 and try to load it inside 2004.
-If your application uses another DLLs they need to be placed into a known system folder or at the same folder of ARX file.
-If your project was built with ARXWizard 2006 it will not created the .DEF file and this will avoid it to be loaded on AutoCAD 2005 and 2004. Create this file and add it to the project.
-Your acrxEntryPoint() function is returning something different it should return (AcRx::kRetOK).
Regards,
Fernando.
Olá fernando...
Estava precisando saber se com essa ferramenta ObjectARX eu poderia criar um programinha onde eu tenho um desenho feito no autocad com vários círculos e o meu programa pudesse me retornar todas as coordenadas dos centros do círculos??? Isto é um projeto de faculdade que estou fazendo.... por isso gostaria de saber para eu poder começar a estudar ObjectARX!!
Muito obrigado pela atenção!!
Olá Marcos.
Basicamente você precisa selecionar todo o desenho, abrir cada entidade encontrada para leitura.
A classe AcDbCircle representa a entidade círculo do AutoCAD. Sendo assim, ao abrir as entidades como AcDbEntity (a classe base) você pode testar se ela é um círculo da seguinte forma:
// Obter o ponteiro para cada entidade presente no desenho
AcDbEntity* pEnt = NULL;
// Tentar fazer um cast para círculo
AcDbCircle* pCirc = AcDbCircle::cast(pEnt);
Se o pCirc for diferente de NULL é porque a entidade é um círculo.
A partir do pCirc, você pode acessar os métodos específicos que lhe retornam todos os dados incluindo o ponto do centro.
Dê uma olhada no meu Blog para maiores informações de como selecionar as entidades, como abrir, etc.
Abraços,
Fernando.
Olá fernando.... tudo joia?
Ja vi q da sim para eu fazer meu projeto com esta ferramenta objectarx... mais estou com uma duvida... com estas bibliotecas do ObjectARX eu poderei criar um executavel no qual eu executo e informo o arquivo .dwg e assim o programa me mostra na tela as coordenadas dos centros do circulos ou essa ferramenta apenas pode ser integrada ao AutoCad??? Andei lendo e me parece que é apenas uma extensão para AutoCad, ou seja, não poderei criar um executavel...
Da ou não para criar um executável do jeito q estou querendo?
Grato pela atenção....
Marco,
ObjectARX só roda dentro do AutoCAD. Se você quiser fazer um aplicativo fora do AutoCAD tem que usar o VB ou mesmo o VC++ só que acessando o AutoCAD via interface COM.
Ainda assim na máquina aonde o programa for rodar você terá que ter o AutoCAD instalado.
Para fazer uma rotina que não dependa do AutoCAD você poderia analisar os dados de um arquivo DXF gerado pelo AutoCAD. Ele é um arquivo texto.
Para testar, abra um desenho e crie um círculo nele. Salve como DXF e abra no Notepad para ver como ele salva as informações do círculo e de seu centro.
Boa sorte.
Abraços,
Fernando.
Dear Fernanod,
Please How to get user instead of Anonymous user.
Regards,
M.S
Hi M.S,
Sory I did not understand your question. What type of user are you talking about?
Regards.
Dear Fernando,
user on this web site
Regards,
M.s
You need a Blogger account.
Take a look at:
http://www.blogger.com
Regards.
Dear Fernanod,
In this code i have memory leak in variant variable what is the reason.
VARIANT variant;
VariantInit(&variant);
_bstr_t bstr = value;
V_VT(&variant) = VT_BSTR;
V_BSTR(&variant) = SysAllocString(bstr);// bstr;
AcMapObjClass::EErrCode err ;
err = PropArray.at(i)->SetValue(ObjId, &variant, false) ;
if(err==AcMapObjClass::ePropertyNotFound)
counNotUpdate++;
VariantClear(&variant);
delete &variant;
Do you have any idea.
M.S,
Regards.
Hi M.S,
Without see the complete code it is difficult to find out the reason.
Have you tried to free the string with SysFreeString()?
Try to comment out some blocks of your code and see what happens with the memory.
Regards.
Dear Fernanod,
this is my code,
It is very long(work on Map3d 2006).
-Every time when use variant variable I got Memory Leak
-This code copy value of object data to other object data
bool CopyObjectDataToObjectDataCls::StartProcess(void)
{
char * pcname = NULL;
AcMapSession *mapApi2 = NULL;
mapApi2 = AcMapGetSession();
if (mapApi2->GetCurrentUser(pcname, Adesk::kFalse) != AcMap::kOk)
{
acutPrintf("\nError! Not LogIN");
return false;
}
//acutPrintf("_%s_",pcname);
delete [] pcname;
char * filePath;
if ( GetFtrDefFileAtt(filePath) == AcMapObjClass::eNoSchemaFileAttached )
{
acutPrintf("\nError! No file is attached!");
return false;
}
delete filePath;
AcMapClassificationManager *pClsFcnMgr =new AcMapClassificationManager(acdbHostApplicationServices()->workingDatabase());
AcMapObjClassDefinition *PClassDef;
PopertyArray PropArray;
int numberOfMpolygon = 0;
int counNotUpdate = 0;
int totalCounter = 0;
int counUpdate = 0;
int rc;
char ClassAttName[256];
char objDataName[256];
char ClassName[256];
char attName[256];
AcDbObjectId* IdS = SelectMultiMpolygon(numberOfMpolygon);
rc = acedGetString(0, "\nEnter object data name:", objDataName);
switch(rc)
{
case RTCAN:
acutPrintf("\nUserCanceled");
return false;
case RTERROR:
acutPrintf("\nError with input in object name:");
return false;
case RTNONE:
acutPrintf("\nError! Empty string for object data name invalid.");
return false;
}
rc = acedGetString(0, "\nEnter attribute name: ",attName);
switch(rc)
{
case RTCAN:
acutPrintf("\nUserCanceled.");
return false;
case RTERROR:
acutPrintf("\nError with input in attribute name.");
return false;
case RTNONE:
acutPrintf("\nError! Empty string for attribute name invalid.");
return false;
}
rc = acedGetString(0, "\nEnter Feature Class Name:", ClassName);
switch(rc)
{
case RTCAN:
acutPrintf("\nUserCanceled");
return false;
case RTERROR:
acutPrintf("\nError with input in feature class name:");
return false;
case RTNONE:
acutPrintf("\nError! Empty string for feature data name invalid.");
return false;
}
AcMapObjClass::EErrCode errorCode;
errorCode = pClsFcnMgr->GetFeatureClassDefinition(PClassDef,ClassName);
if(errorCode == AcMapObjClass::eNoUserPrivilegeToAlterSchema)
{
acutPrintf("\nError! Not Login!");
return false;
}
else if(errorCode != AcMapObjClass::eOk)
{
acutPrintf("\nError! Featuer Class name");
return false;
}
AcMapODContainer *pODCont = NULL;
AcMapSession *mapApi = NULL;
AcMapProject *pProj = NULL;
mapApi = AcMapGetSession();
mapApi -> GetProject(pProj);
pProj -> GetODContainer(pODCont);
rc = acedGetString(0, "\nEnter Feature Class attribute Name:", ClassAttName);
switch(rc)
{
case RTCAN:
acutPrintf("\nUserCanceled");
return false;
case RTERROR:
acutPrintf("\nError with input in feature class attribute name:");
return false;
case RTNONE:
acutPrintf("\nError! Empty string for feature class attribute name invalid.");
return false;
}
PClassDef->GetProperties(PropArray);
bool isFound = false;
for(int i = 0; i < PropArray.length(); i++)
{
const char* name = PropArray.at(i)->GetName();
if(strcmp(name , ClassAttName) == 0)
{
isFound = true;
for(int z = 0; z < numberOfMpolygon; z++)
{
AcDbObjectId ObjId = IdS[z];
char value[256];
GetValForObjDataAtt(IdS[z], pODCont, objDataName, attName, value);
VARIANT variant;
VariantInit(&variant);
_bstr_t bstr = value;
V_VT(&variant) = VT_BSTR;
V_BSTR(&variant) = SysAllocString(bstr);// bstr;
AcMapObjClass::EErrCode err ;
err = PropArray.at(i)->SetValue(ObjId, &variant, false) ;
if(err ==AcMapObjClass::ePropertyNotFound)
counNotUpdate++;
VariantClear(&variant);
delete &variant;
}
for(int i = 0; i < PropArray.length(); i++)
{
delete (AcMapObjClassProperty*)(PropArray.at(i));
}
break;
}
}
if(!isFound)
{
counNotUpdate++;
}
totalCounter = numberOfMpolygon;
counUpdate = totalCounter-counNotUpdate;
acutPrintf("\n%d Total" ,totalCounter );
acutPrintf("\n%d Updated" , counUpdate );
acutPrintf("\n%d Not Update", counNotUpdate);
delete[] IdS;
return true;
}
Do you have any idea?...
Regards,
M.S
Hi M.S,
I don't have MAP API here to check what each class/method does but some supicious are:
1) delete [] pcname;
Should not be delete pcname ?
(without [])
2) The pointer pClsFcnMgr is never deleted.
3) Call SysFreeString(bstr) before VariantClear().
Regards.
Hi Fernando,
please how to straming AutoCAD file over the intranet?
Regards,
Sarah
I am trying to manage some DWG drawings in Sharepoint Portal Server 2003. It does not appear that I have the capability to edit these documents and save directly to the server.
Regards,
Sarah
Hello Sarah,
I don't know exactly what are the type of modifications you would like to allow to these DWG after send them but I would recommend you to use DWF technology to share them with other users.
With AutoCAD 2008 there are a lot of great tools to deal with DWF files and markup issues.
If you still need to deal with the original DWG file I would recommend you to use Autodesk Vault technology.
More information about these technologies at:
http://www.autodesk.com/dwf
http://www.autodesk.com/vault
Regards,
Hi Fernando,
I mean...
I need to save DWG file to portal in share point(Save file on Http).
In my case I have webSite, I need to allow people to save DWG file on this site and allow people to open file from this web site(Not upload DWG and download)
My procedure to Do this.
1- click saveAs from file menu
2- choose folder (Share point folder)
3- save file
But when i Do this procedure I got
error MSG:"Unable to save file on specified server. To avoid losing your changes, save a copy of the file to another location"
Note: I have privilege to save a file.
Other Note:
1) I can save DWG file over the network but I can't save it over the Internet
2) Share point folder is a logical folder (not Physical folder).
Do you Have any Idea
Regards,
Sarah
Hi Sarah,
As long as you are editing the DWG file AutoCAD keeps a DWL (drawing lock) control file in the same folder. Maybe AutoCAD is having problems while creating this lock file.
If you use other applications like Microsoft Word you are able to save it to the same server?
What about copy the DWG file with Windows Explorer and open it from AutoCAD? Does it works?
Regards,
Hi Fernanod,
- what do you mean by (DWL drawing lock) and how to find this file
-I am in acompany now and I try the same procedure from other computer but I got the same Massage
- I Can Save Word Document to this folder.
Regards,
sarah
Sarah,
Whenever you start to work with a drawing on write-mode (which is the default) AutoCAD create a DWL file with the same name of DWG inside the same folder.
This file stays there until you close the drawing.
Maybe your server is refusing to accept this file which needs to be created and used by AutoCAD.
From AutoCAD Help:
"The information displayed by WHOHAS is stored in a temporary DWL (drawing lock) file. A DWL file is automatically created when a file is opened and then deleted when the file is closed."
Regards,
Hi Fernando,
sorry for bad English...I am from medial East.
The problem not only save the file, when i try to open file(file already Existing in share point folder) I can't see it from file explorer
someone in the company tell me : No Way to save to internet and the only way is from FTP (Is Right???)!!!
sarah
Sarah,
Note that AutoCAD needs to create the DWL file even if the file already exits.
What happens if you try to open the DWG located at this server as ReadOnly (in this case AutoCAD will not try to create the DWL file)?
Regards,
Hi Fernando,
Until now I can't understand what is the solution for DWL file problem.
Is the solution Create instance of this file in the Server??????
Regards,
Sarah
Sarah,
I'm not sure if the DWL file is the cause of your problem but we need to consider it as a possible cause.
To check that you need:
- Try to open a DWG file located at this server using Read Only option at AutoCAD Open File dialog (lower right Open buttom);
- If this works your server is probably blocking the creation of this DWL file;
- If the read only opening does not work too you will need to do more scenarios to find out what is wrong.
I don´t know SharePoint so maybe the problem is related to it and not to AutoCAD itself.
Regards,
Hi Fernando,
I save DWG file manually in share point server folder.
then I do this procedure
1- open AutoCAD
2- From file menu I Choose open
3- From File explorer I choose Share point server But I Can't see any Autocad file in this explorer to open it.
But When i open file from web Site I can open it only for read
So I think the promblem is DWL file
How to solve this problem.
Best Regards,
Sarah
Sarah,
As I said I don't know how SharePoint works but the problem is probably related to permissions of file creation at the folder.
Check if SharePoint have some restrictions to this and your IIS server too (as far as I remember IIS blocks by default the file creation inside web folders).
Sorry but I can't think any other cause of this problem.
Regards,
Hi Fernando,
I solved my problem(Share point) by using tools from this link
http://cadtowin.com/index_files/DownloadArea.html
Thank you Again Fernando
Regards,
Your small sister
Sarah,
You've been kicked (a good thing) - Trackback from CadKicks.com
http://www.cadkicks.com/adkautocad/ObjectARX_Dummies
Hi Fernando,
I looked at the API docs from the Autocad SDK which I downloaded (Map ObjectARX SDK 2009) and I could not see any of the methods and classes you show in your course (except for the AcDbDatabase - which is not described in the API documentation).
The API describes the AcMapSession, AcMapProject, ApMapDrawingSets, and use those mappings to organize objects model. But they does not describe the real drawing objects and commands.
You on the other hand, describe the drawing objects and methods (ex. how to add lines in containers and so on), but you use a different approach to manipulate the drawing objects (acdbHostApplicationServices()->workingDatabase()), and I don't know how it relates with the AcMapSession approach.
I wonder how the ObjectARX classes described in the SDK API can be used to get to the drawing objects and why you did not use that classes. It seems as if there are two halves of the documentation and each one (you on the one hand and the SDK API on the other) describe one of the halves.
Where can I get the whole API? Is it freely available anywhere? Many of the SDK API is described for .NET, but I need all of it for C++ development. As far as the API is concerned, there is an ObjectARX documentation and a GeoSpatial Platform API, but the latter is available for .NET only.
Could you (or any one reading this) help me to find the documentation I need?
Paulo Crestani.
Hello Paulo,
The Autodesk MAP is a product built on the top of AutoCAD using AutoCAD OEM technology.
Due that it has two APIs. The first is the standard ObjectARX SDK which is required to access the AutoCAD Core API.
Autodesk MAP as some other verticals has its own class set and thus its own API which completes the core API with additional classes as you have discovered.
If you need only to use AutoCAD Core API even from inside other verticals you need only standard ObjectARX. In other hand, if you plan to use specific MAP features you will need the standard ObjectARX SDK plus de specific MAP API.
My Blog is based on the AutoCAD Core API so all provided code and samples are based on the Core API.
Hope I have clarified the scenario.
BTW, the standard ObjectARX can be downloaded from:
http://www.objectarx.com
The MAP API can be downloaded here:
http://usa.autodesk.com/adsk/servlet/index?siteID=123112&id=868220
Regards,
Fernando Malard
Hi Fernando,
do you now if it is posible to program with J++ using ObjectARX.
What is true about this article?
http://aecnews.com/articles/399.aspx
Thanks a lot,
Lautaro
Lautaro,
I dont think it is possible.
You can use .NET based languages like C#, VB.NET, F# and proabably J# to create applications but J++ is based on virtual machine, etc.
If it communicate with AutoCAD through its COM interface you can virtually use any language you want (this is the idea of COM, a generic language interface).
Regards,
Oi Fernando.
Gostaria de saber, se programas construídos baseados em ADS, se compilados novamente podem funcionar numa versão como a 2009.
Por outro lado, sabes como fazer rodar o AutoCad R12 Windows no XP.
É que desenvolvi anos atrás um aplicativo ainda em ADS, e gostari a de colocá-lo em funcionamento.
Obrigado.
Nilson
Oi Nilson,
Você pode aproveitar algumas coisas do ADS mas quase tudo muda para o ObjectARX.
Além disso, você precisa fazer o seu código ser UNICODE e ainda implementar suporte ao x64 no seu código.
Talvez seja melhor reescrever tudo mantendo somente a lógica do aplicativo.
Quanto ao AutoCAD R12, acho que não tem jeito mesmo. Tente usar uma máquina Virtual como o VirtualPC 2007 ou VMWare.
Abraços,
Hi Fernando,
I was wondering if there is a way to communicate Autocad with an Application I'm making in MFC, basically I'd like to access the Autocad Database from my stand-alone program.
For example, I'd like to give the 2 vertex of a line in my program and be able to see the line in Autocad (if I change those vertex in my program, Autocad should be able to refresh and draw the line again) and viceversa, if I change the size of the line in Autocad, I'd like to detect when that happens so I can modify my data in my program...
I hope my question makes sense..
Thanks, saludos desde Mexico
Hello,
This level of integration you want can be done by making your application a COM client of AutoCAD COM interface making calls and receving events from it.
This is a very complex coding scenario and maybe you should consider to run your application inside AutoCAD to keep things simple.
If you really need it to run outside AutoCAD, COM is the best way to automate AutoCAD from outside.
Note that are some limitations of COM inside x64 systems in regards to in-process calls.
Here you can find more info about COM Interop:
http://through-the-interface.typepad.com/through_the_interface/2006/09/com_vs_net_in_a.html
Regards.
Fernando,
Thank you very much for your answer... I tried to convince my boss I'd be simpler to adapt the code I have to work inside Autocad but he still thinks it's best to run it as a different application, now I have a point to start.
Thank you.
hi Fernando,
I want to create new blocktablerecord from existing blocktablerecord by copying all entities from existing blocktablerecod to a newl blocktablerecod.
Following is the code i have written. which is not working.
can you help in this ? One more thing if i add a new entity such as line and add it to new blocktablerecord it works fine
AcDbBlockTableRecord *pBlkRec =NULL;
Acad::ErrorStatus es = pBlkTbl->getAt(_T("*MODEL_SPACE"),pBlkRec, AcDb::kForRead);
if(es == Acad::eOk)
{
AcDbBlockTableRecord *pBlkRecNew = new AcDbBlockTableRecord;
pBlkRecNew->setName(_T("Model_Space"));
pBlkTbl->add(pBlkRecNew);
AcDbBlockTableRecordIterator *pBlockIter = NULL;
pBlkRec->newIterator(pBlockIter);
Acad::ErrorStatus es;
for (; !pBlockIter->done(); pBlockIter->step())
{
AcDbEntity *pEnt;
AcDbObjectId objectId;
pBlockIter->getEntityId(objectId);
es = acdbOpenObject(pEnt,objectId, AcDb::kForWrite);
if( es == Acad::eOk)
{
AcDbEntity *pClone = (AcDbEntity *) pEnt->clone();
Acad::ErrorStatus es3 = pBlkRecNew->appendAcDbEntity(pEnt);
pEnt->close();
}
}
pBlkTbl->close();
pBlkRecNew->close();
}
Hello sandy,
There is a much better way to do that. Take a look at AcDbDatabase::wblockCloneObjects() method.
A brief description extracted from the SDK documentation:
Acad::ErrorStatus wblockCloneObjects(
AcDbObjectIdArray& objectIds,
AcDbObjectId& owner,
AcDbIdMapping& idMap,
AcDb::DuplicateRecordCloning drc,
bool deferXlation = false
);
"Clones all objects in the objectIds array and appends them to the container object specified by owner. The objects can be from multiple source databases, and must match the type of owner supplied, but must be from a different database than the owner object."
So you just need to create the new BlockTableRecord and use this method to clone all objects from the source BlockTableRecord.
Hope this help.
Hi,
thanks for quick reply.
Here is a slight problem. Both the blocktablerecords are from same database. Do we have anything else that can be used for copying / cloning between same datbase blocktablerecords.
Thanks
sandy,
"The objects can be from multiple sources"...
It should work inside the same database. Just give a try.
Regards.
Thanks,
My problem is resolved.
In Stead on calling.
getEntityId() & using id then calling getEntity(),
I replaced with getEntity()
Hi Fernando,
I have a development scenario, please help me if you have any idea.
I have a drawing, with one modespace and one paperspace layout.
Paperspace layout has a viewport focusing on small area on modelspace.
Now i want get all entities from this paperspace layout (viewport) and add them to modelspace as BlockReference.
Thanks in Advance.
Sandy
Hello sandy,
Well, the Layout is a BlockTableRecord as the Modelspace so you can copy every entity inside it to the Modelspace.
What is inside the viewport is not actually there, it is just a zoom view of some Modelspace area.
So the same clone procedure you are using inside Modelspace can work from PaperSpace too.
Regards.
Hi Fernando,
Paperspace block table record doesnt contains any entities from modelspace. It has single entity AcdbViewport. its not possible to get entities from paperspace layout blocktablerecord just like form modelsapce blocktablerecord.
Thanks
sandy,
You did get me wrong.
What I wanted to explain is PaperSpace may contain its own entities and some of them will be the viewports you use. Inside the viewports there are no entities, it is just a view of some portion of ModelSpace.
Exactly due that, when you double click inside a Viewport you are actually editing the original Modelspace.
If you want to select the original entities that are visibile into some specific viewport you will need to do some selection filter by mapping the viewport coordinates to the Modelspace. With this "window" you can go back to Modelspace and select the actual entities.
Regards.
Thats correct. But how do you will select the entities coming under that window, if you are using RealDWG ( i.e. AcedGet* functions are not available.)
thanks
Well, in this case it will be difficult because there is no easy way to select entities without aced methods.
One possible solution would be use the intersectWith() capability of entities. In this case you could create some polygon or region with the same viewport geometry, translate it into ModelSpace coordinates and then check the intersection with entities.
But I'm not sure this will work for entities entirely inside the viewport without touching its boundary.
Can't think any other alternative right now...
hi fernando !
could i questioning programs about AutoLisp in this ObjectARX blog ?
if not
or any other a proper place for posting Autolisp comments and gets solutions from experts like you !
Hello Jimmy,
The idea of this Blog is to focus on ObjectARX and I'm not an expert to help you with LISP issues.
Sorry about that.
thank !
Post a Comment