|
AcDb: deriving from AcDbPolyline
问题:
Deriving from AcDbPolyline works correctly, however, it seems DWG files
containing instances of my custom entity derived from AcDbPolyline do not
contain proxy graphic information for them. Why?
解答:
AutoCAD does not save the proxy graphic information for classes derived from
AcDbPolyline. The reason for this is that the 'saveAs()' method is implemented
as follows:
普通浏览复制代码
void AcDbPolyline::saveAs(AcGiWorldDraw* mode, AcDb::SaveType st) {
assertReadEnabled();
if ( st == AcDb::kR12Save )
// ... do something to convert into AcDb2dPolyline
}
Whereas it should be as follows:
普通浏览复制代码
void AcDbPolyline::saveAs(AcGiWorldDraw* mode, AcDb::SaveType st) {
assertReadEnabled();
if ( st == AcDb::kR12Save )
// ... do something to convert into AcDb2dPolyline
else
worldDraw (mode) ;
}
As a result, proxy graphic data is never saved, which causes your derived
AcDbPolyline entity to be invisible if your DBX-object enabler application is
not loaded. Although this is not ideal, it does not affect any other behavior or
functionality of your custom entity.
A simple override of the 'saveAs()' method can solve this problem as follows:
普通浏览复制代码
void AcDbMyPolyline::saveAs(AcGiWorldDraw* mode, AcDb::SaveType st) {
assertReadEnabled();
if ( st == AcDb::kR12Save )
AcDbPolyline::saveAs (mode, st) ;
else
worldDraw (mode) ;
}
This would be the correct solution, however there is another known problem in
AutoCAD that prevents the 'saveAs()' method from being called for proxy graphic
generation. This second problem is more serious because it prevents 'saveAs()'
method being called. The reason for this is that AutoCAD makes an exception in
the case of an AcDbPolyline entity. Instead of asking 'are you an AcDbPolyline
class?', AutoCAD asks 'Are you a "kind of" AcDbPolyline?' This also includes any
of your derived classes from AcDbPolyline.
The only solution is to pretend your custom AcDbPolyline entity is not an
AcDbPolyline class, even if it really is. This will cause AutoCAD to properly
call the 'saveAs()' method and then your implementation of the 'worldDraw()'
method for your custom entity. In order to pretend that it is not an
AcDbPolyline entity, just implement the 'ACRX_DXF_DEFINE_MEMBERS' ARX macro as
follows:
普通浏览复制代码
ACRX_DXF_DEFINE_MEMBERS(AcDbMyPolyline, AcDbCurve,
AcDb::kDHL_CURRENT, AcDb::kMReleaseCurrent,
AcDbProxyEntity::kNoOperation,
ACDBMYPOLYLINE, ACDBMYAPP
);
There are other requirements in the implemention of the 'worldDraw()' method:
you should not call AcDbPolyline::worldDraw() when called from the 'saveAs()'
method because this would cause the same problem that was outlined previously.
(AutoCAD filters out all AcDbPolyline calls in that context). An 'unhandled
exception error' will occur as a result. (rememeber we are pretending not to be
an AcDbPolyline entity). To solve the problem, you need to modify the 'saveAs()'
method like this:
普通浏览复制代码
bool mbDrawWithExplode = false ;
void AcDbMyPolyline::saveAs(AcGiWorldDraw* mode, AcDb::SaveType st) {
assertReadEnabled();
if ( st == AcDb::kR12Save ) {
AcDbPolyline::saveAs (mode, st) ;
} else {
mbDrawWithExplode = true ;
worldDraw (mode) ;
mbDrawWithExplode = false ;
}
}
Implement your 'worldDraw()' method like this:
Adesk::Boolean AsdkOPLine::worldDraw(AcGiWorldDraw* mode)
{
assertReadEnabled();
if ( !mbDrawWithExplode ) {
bPEdit =true ;
if ( AcDbPolyline::worldDraw (mode) != Adesk::kTrue ) {
bPEdit =false ;
return (Adesk::kFalse) ;
}
bPEdit =false ;
} else {
AcDbVoidPtrArray ents ;
AcDbPolyline::explode (ents) ;
for ( int j =ents.length () - 1 ; j >= 0 ; j-- ) {
((AcDbEntity *)ents.at (j))->worldDraw (mode) ;
delete (AcDbEntity *)ents.at (j) ;
}
ents.setLogicalLength (0) ;
}
return (Adesk::kTrue) ;
} |
|