|
- AcDb: deriving from AcDbPolyline
- Published date: 2008-10-14
- ID: TS47354
- Applies to:
- AutoCAD® 2009
- AutoCAD® 2008
- AutoCAD® 2007
- 问题:
- 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) ;
- }
- If you pretend it is not an AcDbPolyline, the AutoCAD "采用PEDIT" command will not
- work for your custom entity anymore. If you do not intend to support "采用PEDIT",
- then it is not a problem. However, if you intend to support "采用PEDIT" then you
- need to pretend that it is an AcDbPolyline only for the "采用PEDIT" command. To
- support "采用PEDIT" for a special class requires a considerable amount of work.
- First, you need to rewrite the 'ACRX采用DXF采用DEFINE采用MEMBERS' ARX macro like this:
- bool bPEdit =false ;
- void set采用bPEdit (bool flag) {
- bPEdit =flag ;
- }
- //------------------------------------------
- #define MY采用ACRX采用DEFINE采用MEMBERS(CLASS采用NAME) \
- AcRxClass* CLASS采用NAME::desc() \
- { \
- return (AcRxClass*)((AcRxDictionary*)acrxSysRegistry() \
- ->at(ACRX采用CLASS采用DICTIONARY))->at(bPEdit ? "AcDbPolyline" :
- "AcDbMyPolyline"); \
- } \
- AcRxClass* CLASS采用NAME::isA() const \
- { \
- return (AcRxClass*)((AcRxDictionary*)acrxSysRegistry() \
- ->at(ACRX采用CLASS采用DICTIONARY))->at(bPEdit ? "AcDbPolyline" :
- "AcDbMyPolyline"); \
- } \
- AcRxClass* CLASS采用NAME::gpDesc = NULL
- //----------------------------------------------------------------------
- #define MY采用ACRX采用DXF采用DEFINE采用MEMBERS(CLASS采用NAME,PARENT采用CLASS,DWG采用VERSION,\
- MAINTENANCE采用VERSION,PROXY采用FLAGS,DXF采用NAME,APP) \
- MY采用ACRX采用DEFINE采用MEMBERS(CLASS采用NAME); \
- static AcRxObject * make##CLASS采用NAME() { return new CLASS采用NAME(); } \
- void CLASS采用NAME::rxInit() { \
- if (CLASS采用NAME::gpDesc != NULL) \
- return; \
- CLASS采用NAME::gpDesc = newAcRxClass(#CLASS采用NAME, #PARENT采用CLASS, \
- DWG采用VERSION,MAINTENANCE采用VERSION,PROXY采用FLAGS, \
- &make##CLASS采用NAME, #DXF采用NAME, #APP); \
- }
- Replace the 'ACRX采用DXF采用DEFINE采用MEMBERS' ARX macro with the following definition:
- MY采用ACRX采用DXF采用DEFINE采用MEMBERS(AcDbMyPolyline, AcDbCurve,
- AcDb::kDHL采用CURRENT, AcDb::kMReleaseCurrent,
- AcDbProxyEntity::kNoOperation,
- ACDBMYPOLYLINE, ACDBMYAPP
- );
- The last item you need to implement is an AcEditorReactor to detect when the
- "采用PEDIT" command is executed and set the pPEdit flag to True as follows:
- void AsdkEdReactor::commandWillStart(const TCHAR* cmdStr)
- {
- if ( 采用tcsicmp (cmdStr, 采用T("PEDIT")) == 0 )
- set采用bPEdit (true) ;
- }
- void AsdkEdReactor::commandEnded(const TCHAR* cmdStr)
- {
- if ( 采用tcsicmp (cmdStr, 采用T("PEDIT")) == 0 )
- set采用bPEdit (false) ;
- }
- void AsdkEdReactor::commandCancelled(const TCHAR* cmdStr)
- {
- if ( 采用tcsicmp (cmdStr, 采用T("PEDIT")) == 0 )
- set采用bPEdit (false) ;
- }
- void AsdkEdReactor::commandFailed(const TCHAR* cmdStr)
- {
- if ( 采用tcsicmp (cmdStr, 采用T("PEDIT")) == 0 )
- set采用bPEdit (false) ;
- }
复制代码 |
|