Tuesday, March 15, 2005

Lab 1 - Creating and Editing Entities

Hello,

Our first Lab will cover all presented contents since the course beginning. The main idea is to keep this lab simple to consolidate all knowledge present so far.

Requirements:

* Class 1 to 6;
* AutoCAD 2004/2005 or compatible vertical installed;
* Visual Studio .NET 2002 installed;
* ObjectARX Wizard installed.

Objectives:

Create a simple ObjectARX module with 2 commands: CENTS and CHENTS. The first command will create a simple circle (center on 0,0,0 - radius = 10) and a line (from 0,0,0 to 10,10,0). The second command will prompt user to select an existing entity and then will change its color to 1(red).

Instructions:

- Create a project called ARXLAB1 using ObjectARX Wizard;
- Click on the a> icon at ARXWizard's toolbar to open command dialog;
- Right click on the above portion and select New;
- Change the global an local name for CENTS and select Modal as command mode;
- Repeat the process for the CHENTS command;
- Click OK and inspect acrxEntryPoint.cpp file to see the two created functions;
- Observe that two MACRO entries were added at the end of this file;
- To select an entity to change its color, use the following procedure (trust me):

ads_name en;
ads_point pt;
if (acedEntSel(_T(
"\nSelect an entity: "), en, pt) == RTNORM) {
AcDbObjectId eId = AcDbObjectId::kNull;
acdbGetObjectId(eId, en);
}


Tips:

- Don't forget to call close() the entities after open or create them;
- Explore the code to understand what ARX Wizard has created for you;
- Pay attention to code syntax;
- Use the ObjectARX documentation when necessary;

Support:

If you have any questions please post your issue on this article to share with others.

Expected time:

- I will give you 3 days to accomplish this Lab;
- After this period, I will post my suggested solution for this.

8 comments :

Ike said...

I'm a newb so go easy on me.

I have edited the code for 'acrxEntryPoint.cpp' and have pasted the ccode to look as follows...

[START of my code]

/ (C) Copyright 2002-2005 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//

//-----------------------------------------------------------------------------
//----- acrxEntryPoint.h
//-----------------------------------------------------------------------------
#include "StdAfx.h"
#include "resource.h"

//-----------------------------------------------------------------------------
#define szRDS _RXST("SFDT")

//-----------------------------------------------------------------------------
//----- ObjectARX EntryPoint
class CARXLAB1App : public AcRxArxApp {

public:
CARXLAB1App () : AcRxArxApp () {}

virtual AcRx::AppRetCode On_kInitAppMsg (void *pkt) {
// TODO: Load dependencies here

// You *must* call On_kInitAppMsg here
AcRx::AppRetCode retCode =AcRxArxApp::On_kInitAppMsg (pkt) ;

// TODO: Add your initialization code here

return (retCode) ;
}

virtual AcRx::AppRetCode On_kUnloadAppMsg (void *pkt) {
// TODO: Add your code here
// Add your code for command SFDTARXLAB1._CHENTS here
ads_name en;
ads_point pt;
if (acedEntSel("\nSelect an entity: ", en, pt) == RTNORM) {
AcDbObjectId eId = AcDbObjectId::kNull;
acdbGetObjectId(eId, en);
}
// You *must* call On_kUnloadAppMsg here
AcRx::AppRetCode retCode =AcRxArxApp::On_kUnloadAppMsg (pkt) ;

// TODO: Unload dependencies here

return (retCode) ;
}

virtual void RegisterServerComponents () {
}

public:

// - SFDTARXLAB1._CENTS command (do not rename)
static void SFDTARXLAB1_CENTS (void)
{
// Add your code for command SFDTARXLAB1._CENTS here

}
public:

// - SFDTARXLAB1._CHENTS command (do not rename)
static void SFDTARXLAB1_CHENTS(void)
{
// Add your code for command SFDTARXLAB1._CHENTS here

}
} ;

//-----------------------------------------------------------------------------
IMPLEMENT_ARX_ENTRYPOINT(CARXLAB1App)

ACED_ARXCOMMAND_ENTRY_AUTO(CARXLAB1App, SFDTARXLAB1, _CENTS , CENTS , ACRX_CMD_MODAL, NULL)
ACED_ARXCOMMAND_ENTRY_AUTO(CARXLAB1App, SFDTARXLAB1, _CHENTS, CHENTS, ACRX_CMD_MODAL, NULL)

[END of my code]

When I guild the project I get the error...

1>Compiling...
1>acrxEntryPoint.cpp
1>e:\data\eds_nmci\programming\objectarx\projects\arxlab1\arxlab1\acrxentrypoint.cpp(54) : error C2664: 'acedEntSel' : cannot convert parameter 1 from 'const char [20]' to 'const ACHAR *'
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>Build log was saved at "file://e:\Data\EDS_NMCI\Programming\ObjectARX\Projects\ARXLAB1\ARXLAB1\Debug\BuildLog.htm"
1>ARXLAB1 - 1 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Not sure what to do at this point?

Thanks

Fernando Malard said...

Hi Ike,

The problem is related to this line:

if (acedEntSel("\nSelect an entity: ", en, pt) == RTNORM) {

As you are using ObjectARX 2007 or 2007 you need to support UNICODE.
Change that line to:

if (acedEntSel(_T("\nSelect an entity: "), en, pt) == RTNORM) {

The _T() macro will do the magic. Please take a look at UNICODE section at your ObjectARX 2007/2008 migration guide.

Best regards,

Anonymous said...

Hi Fernando,

How can I add menu items to the AutoCAD shortcut menu (when you right click) whenever my entity is selected? In AutoCAD, when you draw say a linear dimension, select it and right click, there are more options listed. This is what I want to do and then wright callbacks to handle them.

Fernando Malard said...

Hi,

Basically you will need to derive a context class from AcEdUIContext.
Next, bind the instance of this class through acedAddObjectContextMenu() method passing in your class descriptor.

There is a sample showing how to do this in details:

\ObjectARX 2007\samples\editor\mfcsamps\contextmenu

Regards,

Racso said...

Hi Fernando:
I’m having a problem with ObjectARX 2013. I cannot find a way to open the command dialog. In ObjectARX 2012 it was easy, just clicking the a> icon as you show in Lab1. But ObjectARX 2013 does NOT have those icons any more. I found how to create MFC class in ObjectARX 2013: Project->Add Class-> MFC Support Class Wizard…….. but I could not find the way to get the command dialog. Could you show me how to do it?
Thanks a lot and have a good day.

Oscar.

Fernando Malard said...

Hi Oscar,

Actually there is no Toolbar for 2013. All features were placed into Application and Class Wizards context.

The command dialog is gone and it was replaced by a MACRO documented inside ARX Help. If you create a default ARX project you will see that macro being used do declare and define the command. Use it as a template and create your command calls.

Hope this help.

Anonymous said...

Hi fernando,

How do we read the coordinates of an entity? I want to draw a 3d solid manually on autocad, now I want to get the specific position on this solid to create another solid?

I want to ask
1.How do I select this solid?
2. and how do I read its coordinate?

Thanks & Regards

Fernando Malard said...

Hi,

It depends what precision you are looking for. If you consider a circle (AcDbCircle) as an example, its "coordinates" can represent its center or one of its quadrants. If you consider a line (AcDbLine) it could be one of its end points or even its mid point.

When dealing with solids (AcDb3dSolid) entities it is going to be tricky. Each solid might be represented by a complex combination of boolean operations, extrusions, revolutions, etc. So I don't know, in this context, what exactly you expect to collect while selecting a generic solid in terms of coordinates.

Fortunately, if you are not looking by a specific precision point, ObjectARX API does provide a handy method called getGeomExtents() which returns a AcDbExtents object representing the entity's bounding box in WCS coordinates.

With this method you could select the solid and obtain this bounding box thus using the box min/max points to properly calculate the coordinates you are looking for (the lower left corner, the box center point, etc.)

As any other entity you can select the solid via the UI interaction commands like acedSSGet() and test the obtained entity. Take a look at this page in my blog for further information about selection sets:

http://arxdummies.blogspot.com.br/2005/03/class-8-selection-sets.html

Hope this help you.