On this class we will cover the first ways we can interact with user to allow our application to get information from drawing screen You probably will need to use this method inside your application.
Introduction
This is one of the most important ways to interact with user because it will allow you to get information from drawing screen through selected entities. Some times you will request user to select entities individually and sometimes you will select them using a filter.
A selection set is a group of entities which are currently selected by an user or by an application. The most important concept involved when selecting entities from screen is that AutoCAD will return their names through a type called ads_name. This type contains the entity name (which is valid only on the current session) and it can be converted to ObjectId using the acdbGetObjectId() global function:
Acad::ErrorStatus acdbGetObjectId (AcDbObjectId& objId, const ads_name objName);
The selection is made using a function called acedSSGet() which will apply a selection or prompt the user to do that. The function signature is:
int acedSSGet (const ACHAR *str, const void *pt1, const void *pt2,
const struct resbuf *entmask, ads_name ss);
It receives a selection option, two points, a mask and returns the resulting selection set. After use the selection set it needs to be released and this is done through the acedSSFree() function The selection option will instruct AutoCAD interface to do one of the following methods:
Selection Code | Description |
---|---|
NULL | Single-point selection (if pt1 is specified) |
# | Nongeometric (all, last, previous) |
:$ | Prompts supplied |
. | User pick |
:? | Other callbacks |
A | All |
B | Box |
C | Crossing |
CP | Crossing Polygon |
:D | Duplicates OK |
:E | Everything in aperture |
F | Fence |
G | Groups |
I | Implied |
:K | Keyword callbacks |
L | Last |
M | Multiple |
P | Previous |
:S | Force single object selection only |
W | Window |
WP | Window Polygon |
X | Extended search (search whole database) |
This way we can perform the selection by several ways. Some examples are presented below:
ads_point pt1, pt2;
ads_name ssname;
pt1[X] = pt1[Y] = pt1[Z] = 0.0;
pt2[X] = pt2[Y] = 5.0; pt2[Z] = 0.0;// Get the current PICKFIRST or ask user for a selection
acedSSGet(NULL, NULL, NULL, NULL, ssname);// Get the current PICKFIRST set
acedSSGet(_T("I"), NULL, NULL, NULL, ssname);// Repeat the previous selection set
acedSSGet(_T("P"), NULL, NULL, NULL, ssname);// Selects the last created entity
acedSSGet(_T("L"), NULL, NULL, NULL, ssname);// Selects entity passing through point (5,5)
acedSSGet(NULL, pt2, NULL, NULL, ssname);// Selects entities inside the window from point (0,0) to (5,5)
acedSSGet(_T("W"), pt1, pt2, NULL, ssname);
Using Selection filters
Filters are a powerful way to speed up selection sets and avoid runtime operations to verify entities. You can use single filters or composed filters. Each filter is specified through a structure called resbuf. A resbuf is a linked list which store several types of information and may contains several items. To use a filter we need to construct it and pass it as a parameters of acedSSGet() method. The selection is performed but each selected entity will need to respect the filter. There are a lot of filters we can create and the SDK documentation cover all of them. The most used examples are presented below:
struct resbuf eb1, eb2;
TCHAR sbuf1[10], sbuf2[10];
ads_name ssname1, ssname2;eb1.restype = 0; // Entity name filter
_tcscpy(sbuf1, _T("CIRCLE"));
eb1.resval.rstring = sbuf1;
eb1.rbnext = NULL;
// Retrieve all circles
acedSSGet(_T("X"), NULL, NULL, &eb1, ssname1);eb2.restype = 8; // Layer name filter
_tcscpy(sbuf2, _T("0"));
eb2.resval.rstring = sbuf2;
eb2.rbnext = NULL;
// Retrieve all entities on layer 0
acedSSGet(_T("X"), NULL, NULL, &eb2, ssname2);
Modifying entities through a selection set
To modify entities inside a selection set we need to walk through selection items, get each one, convert the ads_name to an ObjectId, open the entity for write, modify it and then close it. This operation can also be done using a transaction which is, in long operations, much better.
To show you how to walk through a selection set I will present a short code to select all CIRCLE entities inside the drawing and then change its color to red. The operation is pretty simple and is done this way:
// Construct the filter
struct resbuf eb1;
TCHAR sbuf1[10];
eb1.restype = 0; // Entity name
_tcscpy(sbuf1, _T("CIRCLE"));
eb1.resval.rstring = sbuf1;
eb1.rbnext = NULL;
// Select All Circles
ads_name ss;
if (acedSSGet(_T("X"), NULL, NULL, &eb1, ss) != RTNORM){
acutRelRb(&eb1);
return;
// Free the resbuf
acutRelRb(&eb1);
// Get the length (how many entities were selected)
long length = 0;
if ((acedSSLength( ss, &length ) != RTNORM) (length == 0)) {
acedSSFree( ss );
return;
ads_name ent;
AcDbObjectId id = AcDbObjectId::kNull;
// Walk through the selection set and open each entity
for (long i = 0; i < length; i++) {
if (acedSSName(ss,i,ent) != RTNORM) continue;
if (acdbGetObjectId(id,ent) != Acad::eOk) continue;
AcDbEntity* pEnt = NULL;
if (acdbOpenAcDbEntity(pEnt,id,AcDb::kForWrite) != Acad::eOk)
continue;
// Change color
pEnt->setColorIndex(1);
pEnt->close();
// Free selection
acedSSFree( ss );
I have used some new functions (like acdbOpenAcDbEntity) that are also part of ObjectARX SDK. Pay attention to the memory releases regarding to selection set and resbuf types. Note that I have used also a function called acedSSLength() to get the length of selection set.
See you next class.