Friday, January 12, 2007

Exercise2 - Step5

Creating a Custom Entity – Exercise 2 – Step 5

Sometimes you need to distribute an AutoCAD drawing with custom entities inside. By default, when AutoCAD opens a drawing and find some entity it does not recognize, it protects this entity and packs its binary data into a Proxy entity. The proxy entity protects your object data avoiding unwanted users to manipulate your custom entities.
The proxy entity is merely a dummy entity with a fixed graphical representation. Several features of your custom entity will not be available once your code is not there to provide these methods. If your drawing is opened by an unadvised user that would be nice if you inform this user about the missing application.
The proxy can contain specific graphics which will be generated with a call to your worldDraw() method just before AutoCAD close the drawing. The worldDraw() method has a parameter, an AcGiWorldDraw pointer, that allows you to call a regenType() method to find out if the caller is requesting proxy graphics to your entity. At this time, you can draw a different graphic to make and advertisement of your missing custom entity. The following code shows how to handle the proxy graphics:

// ==================================================================
if (mode->regenType() == kAcGiSaveWorldDrawForProxy)
// Draw dummy text
CString strTxt = _T("AU Polyline");
AcGePoint3d ptTxt = GetPolylineCenter();
mode->geometry().text(ptTxt, AcGeVector3d::kZAxis, AcGeVector3d::kXAxis, szRef, 1.0, 0.0, strTxt);

On this example the proxy graphics will be the standard entity graphic plus a text indicating our class name. You may also add an URL address of your product or company. We will use the center point as this text’s start point.
Unfortunately this solution is not complete for AcDbPolyline derived entities. There is a problem when a polyline needs to generate its proxy graphics and the worldDraw() method is not called. To solve this problem we need to add another method, called saveAs(), to our class. This method has the following declaration:

virtual void saveAs(AcGiWorldDraw * mode, AcDb::SaveType st);
The implementation of this method is as follows:

void AuPolyline::saveAs(AcGiWorldDraw * mode, AcDb::SaveType st)
AcDbPolyline::saveAs (mode, st) ;
if ((mode->regenType() == kAcGiSaveWorldDrawForProxy) &&
(st == AcDb::kR13Save))

This method first forward the call to our base class and then test if the regenType() and the save type is AcDb::kR13Save. If they are, we forward the call to our own worldDraw() method which will draw the custom entity graphic plus the proxy text message.
To test this behavior create some AuPolyline entities, save the drawing, close AutoCAD and then open this DWG without loading the application modules. Once the DWG file is opened you will see a proxy warning dialog with some information about the missing application (Figure 18).

Figure 18 – Proxy Information dialog.

Note on the Figure 18 that our proxy text is displayed and also, at the proxy information dialog, you may find information about the missing application. This dialog allows users to choose one of the 3 options about how AutoCAD will handle its proxy entities. You can also setup the standard proxy behavior accessing Tools > Options > Open and Save.
Remember that the DBX module can be loaded to re-enable the custom entity or you can also send your DBX module along with the DWG file to enable third-party users to see your custom entity with complete information. This way you can provide a full graphical representation without the application interfaces (ARX module). The third-party users will be able to see it but can’t modify the custom entity.
AutoCAD allows some basic operations over the proxy entity like erase, change layer, change color and transformations. These operations will act basically over its dummy graphical representation (they will not affect your custom entity’s data except when it is erased). It is up to the developer to determine the most adequate flags for each custom entity. This is a compiler-time option and it is defined on the custom entity’s class implementation macro (ACRX_DXF_DEFINE_MEMBERS). This flags can be combined to build a complete configuration. Please refer to ObjectARX SDK documentation for further information about proxy flags.

No comments :