Custom point gripped to drag and drop causing AutoCAD2019 crash

hypertent
Enthusiast

Custom point gripped to drag and drop causing AutoCAD2019 crash

hypertent
Enthusiast
Enthusiast

The custom points in my ARX program was able to be gripped and dragged and dropped to destination location. It worked perfectly fine until I ported my ARX program to AutoCAD 2019 version. I haven't got chance to port my ARX program to latest AutoCAD version. But AutoCAD 2019 version has already made me annoyed.  In my 2019 ARX program I got custom point defined as TNTPoint. I tried to grip this point to some position to change my geometry shape but the AutoCAD 2019 crash for no reason. This never happened in my old versions such as AutoCAD 2009. To figure out the reason, I wrote a mockup program by using our classic ARX sample to create the similar TNTPoint inside the sample code. I built the program and loaded the ARX application and gripped my custom point to another position, the same thing happened: AutoCAD 2019 crashed. It looks like AutoCAD 2019 has some bugs for ARX custom entity gripping or some of my custom object definition not right for new ObjectARX . Can someone help me out? My mockup program is as follows:

[code]

#if defined(_DEBUG) && !defined(AC_FULL_DEBUG)
#error _DEBUG should not be defined except in internal Adesk debug builds
#endif

#include <Windows.h>
#include <stdlib.h>
#include "rxobject.h"
#include "rxregsvc.h"
#include "rxdlinkr.h"
#include "rxditer.h"
#include "aced.h"
#include "adslib.h"
#include "dbents.h"
#include "dbregion.h"
#include "dbdict.h"
#include "dbsymtb.h"
#include "dbsymutl.h"
#include "dbapserv.h"
#include "tchar.h"

 


void initApp();
void unloadApp();
extern "C"
AcRx::AppRetCode acrxEntryPoint(AcRx::AppMsgCode, void*);

class TNTPoint : public AcDbPoint
{
public:

ACRX_DECLARE_MEMBERS(TNTPoint);

// Constructor / Destructor
TNTPoint() { mDrawAsCircle = false; }
virtual ~TNTPoint() {}

//{{AFX_ARX_METHODS(TNTPoint)
virtual Acad::ErrorStatus subClose()
{
assertReadEnabled();
return AcDbPoint::subClose();

}
// virtual void list() const; 
virtual Acad::ErrorStatus subErase(Adesk::Boolean erasing)
{
assertReadEnabled();
return AcDbObject::subErase(erasing);
}

virtual Acad::ErrorStatus dwgOutFields(AcDbDwgFiler* pFiler) const
{
assertReadEnabled();
Acad::ErrorStatus es;

if ((es = AcDbPoint::dwgOutFields(pFiler)) != Acad::eOk) {
return es;
}

pFiler->writeItem((Adesk::Int32)mtntNumber);


return pFiler->filerStatus();
}
virtual Acad::ErrorStatus dwgInFields(AcDbDwgFiler* pFiler)
{
assertWriteEnabled();
Acad::ErrorStatus es;

// Call dwgInFields from AcDbPoint
if ((es = AcDbPoint::dwgInFields(pFiler)) != Acad::eOk) {
return es;
}

mDrawAsCircle = false;
pFiler->readItem((Adesk::Int32*)&mtntNumber);

return pFiler->filerStatus();
}
//}}AFX_ARX_METHODS


//{{AFX_ARX_DATA_ACCESS(TNTPoint)
//}}AFX_ARX_DATA_ACCESS

void setDrawAsCircle(bool draw) { mDrawAsCircle = draw; }
//tnt number access functions
int getTNTNumber() { assertReadEnabled(); return mtntNumber; }
void setTNTNumber(int val) { assertWriteEnabled(); mtntNumber = val; }


protected:


virtual void subList() const 
{
assertReadEnabled();
// acutPrintf(_T("\nThe impossible has happened!"));
acutPrintf(_T("\nPoint Number: %d"), mtntNumber);
}
virtual void subViewportDraw(AcGiViewportDraw* pVpDraw) 
{
assertReadEnabled();
//draw a little square to represent the point
assertReadEnabled();
AcGeVector3d ViewDir = pVpDraw->viewport().viewDir();
AcGeVector3d UpVector;
pVpDraw->viewport().getCameraUpVector(UpVector);
AcGeVector3d SideVec = UpVector.crossProduct(ViewDir).normal();

double pointSize = 40.0;
double numberSize = 40.0;
AcGePoint2d PixelPerUnit;
pVpDraw->viewport().getNumPixelsInUnitSquare(position(), PixelPerUnit);
numberSize = numberSize / PixelPerUnit[0];

pointSize = pointSize / PixelPerUnit[0];

if (!mDrawAsCircle)
{
//create corners of the square
AcGePoint3d Pts[5];
Pts[0] = Pts[4] = position() + UpVector.normal()*pointSize / 2.0 + SideVec * pointSize / 2.0;
Pts[1] = Pts[0] - UpVector.normal()*pointSize;
Pts[2] = Pts[1] - SideVec * pointSize;
Pts[3] = Pts[2] + UpVector.normal()*pointSize;
pVpDraw->geometry().polyline(5, Pts);
}
else //draw as circle
{
pVpDraw->geometry().circle(position(), pointSize / 2, ViewDir);
}

// char string[32];
TCHAR string[32];
mtntNumber = 100;
_stprintf(string, _T("%d"), mtntNumber);
pVpDraw->geometry().text(position() + (numberSize)*SideVec - (numberSize / 2)*UpVector, ViewDir, SideVec, numberSize, 1.0, 0.0, string);

}
virtual Adesk::Boolean subWorldDraw(AcGiWorldDraw* mode) 
{
assertReadEnabled();

return Adesk::kFalse;
}

virtual Acad::ErrorStatus subExplode(AcDbVoidPtrArray& entitySet) const 
{
assertReadEnabled();
return AcDbEntity::subExplode(entitySet);
}


private:
//{{AFX_ARX_DATA(TNTPoint)
//}}AFX_ARX_DATA

//transient variable to tell the point to draw as a circle (so the user can see its selected)
bool mDrawAsCircle;

//tnt number which will correspond to its position in the .tnt file
int mtntNumber;

private:

void *operator new[](size_t nSize) { return 0; }
void operator delete[](void *p) {};
void *operator new[](size_t nSize, const TCHAR *file, int line) { return 0; }

};
ACRX_NO_CONS_DEFINE_MEMBERS(TNTPoint, AcDbPoint);

class AsdkEntTemperature : public AcRxObject
//
// AsdkEntTemperature Protocol extension abstract base
// class. Notice that this is the lowest level that uses
// the ACRX macros.
//
{
public:
ACRX_DECLARE_MEMBERS(AsdkEntTemperature);
virtual double reflectedEnergy(AcDbEntity*) const = 0;
};
ACRX_NO_CONS_DEFINE_MEMBERS(AsdkEntTemperature, AcRxObject);


class AsdkDefaultTemperature : public AsdkEntTemperature
//
// Default implementation to be attached to AcDbEntity as a
// catch-all. This guarantees that this protocol extension
// will be found for any entity so the search up the
// AcRxClass tree will not fail and abort AutoCAD.
//
{
public:

virtual double reflectedEnergy(AcDbEntity* pEnt) const;
};


double
AsdkDefaultTemperature::reflectedEnergy(
AcDbEntity* pEnt) const
{
acutPrintf(
_T("\nThis entity has no area, and no reflection.\n"));
return -1.0;
}

class AsdkRegionTemperature : public AsdkEntTemperature
//
// AsdkEntTemperature implementation for Regions.
//
{
public:
virtual double reflectedEnergy(AcDbEntity* pEnt) const;
};

double
AsdkRegionTemperature::reflectedEnergy(
AcDbEntity* pEnt) const
{
AcDbRegion *pRegion = AcDbRegion::cast(pEnt);

if (pRegion == NULL)
acutPrintf(_T("\nThe impossible has happened!"));

// Compute reflected energy as region area multiplied
// by a dummy constant.
//
double retVal;
if (pRegion->getArea(retVal) != Acad::eOk)
return -1.0;

return retVal * 42.0;
}


class AsdkCircleTemperature : public AsdkEntTemperature
//
// AsdkEntTemperature implementation for circles.
{
public:

virtual double reflectedEnergy(AcDbEntity* pEnt) const;
};


double
AsdkCircleTemperature::reflectedEnergy(
AcDbEntity* pEnt) const
{
AcDbCircle *pCircle = AcDbCircle::cast(pEnt);

// Compute reflected energy in manner distinctly
// different than for AcDbRegion.
//
return pCircle->radius() * 6.21 * 42.0;
}

 

// This function has the user select an entity and then
// calls the reflectedEnergy() function in the protocol
// extension class attached to that entity's class.
//
void
energy()
{
AcDbEntity *pEnt;
AcDbObjectId pEntId;
ads_name en;
ads_point pt;

 


ads_point tp;
AcGePoint3d point;
AcDbObjectId PtID;
AcDbDatabase* pDb;
pDb = acdbHostApplicationServices()->workingDatabase();

if (acedGetPoint(NULL, _T("\nChoose location of the Point"), tp) != RTNORM)
{
acutPrintf(_T("No location is selected\n"));
return;
}

TNTPoint* pPoint = new TNTPoint;
pPoint->setColorIndex(6);
pPoint->setPosition(point);

AcDbBlockTableRecord* pRecord;

//open the modelspace block
if (Acad::eOk != acdbOpenAcDbObject((AcDbObject*&)pRecord, acdbSymUtil()->blockModelSpaceId(pDb), AcDb::kForWrite))
return;
//add the entity to the modelspace
if (Acad::eOk != pRecord->appendAcDbEntity(PtID, pPoint))
{
pRecord->close();
return;
}
pRecord->close();
pPoint->close();

 

if (acedEntSel(_T("\nSelect an Entity: "), en, pt)
!= RTNORM)
{
acutPrintf(_T("Nothing Selected\n"));
return;
}
acdbGetObjectId(pEntId, en);
acdbOpenObject(pEnt, pEntId, AcDb::kForRead);

// call the protocol extension class's method
//
double eTemp = ACRX_X_CALL(pEnt,
AsdkEntTemperature)->reflectedEnergy(pEnt);

acutPrintf(_T("\nEnergy == %f\n"), eTemp);
pEnt->close();
}


// Pointers for Protocol Extension Objects. These pointers
// are global so that they can be accessed during
// initialization *and* cleanup
//
AsdkDefaultTemperature *pDefaultTemp;
AsdkRegionTemperature *pRegionTemp;
AsdkCircleTemperature *pCircleTemp;

// Initialization function called from acrxEntryPoint during
// kInitAppMsg case. This function is used to add commands
// to the command stack as well as adding protocol extension
// objects to classes in and custom classes to the ACRX
// runtime class hierarchy.
//
void
initApp()
{
acrxRegisterService(_T("AsdkTemperature"));

AsdkEntTemperature::rxInit();
acrxBuildClassHierarchy();

pDefaultTemp = new AsdkDefaultTemperature();
pRegionTemp = new AsdkRegionTemperature();
pCircleTemp = new AsdkCircleTemperature();

// Add the protocol extension objects to the appropriate
// AcRxClass objects
//
AcDbEntity::desc()->addX(AsdkEntTemperature::desc(),
pDefaultTemp);
AcDbRegion::desc()->addX(AsdkEntTemperature::desc(),
pRegionTemp);
AcDbCircle::desc()->addX(AsdkEntTemperature::desc(),
pCircleTemp);

acedRegCmds->addCommand(_T("ASDK_TEMPERATURE_APP"),
_T("ASDK_ENERGY"), _T("ENERGY"), ACRX_CMD_TRANSPARENT,
energy);
}

void
unloadApp()
{
delete acrxServiceDictionary->remove(_T("AsdkTemperature"));
acedRegCmds->removeGroup(_T("ASDK_TEMPERATURE_APP"));

// Remove protocol extension objects from the AcRxClass
// object tree. This *must* be done before removing the
// AsdkEntTemperature class from the ACRX runtime class
// hierarchy so that the AsdkEntTemperature::desc()
// still exists.
//
AcDbEntity::desc()->delX(AsdkEntTemperature::desc());
delete pDefaultTemp;
AcDbRegion::desc()->delX(AsdkEntTemperature::desc());
delete pRegionTemp;
AcDbCircle::desc()->delX(AsdkEntTemperature::desc());
delete pCircleTemp;

// Remove the AsdkEntTemperature class from the ARX
// runtime class hierarchy.
//
deleteAcRxClass(AsdkEntTemperature::desc());
}


AcRx::AppRetCode
acrxEntryPoint(AcRx::AppMsgCode msg, void* appId)
{
switch (msg) {
case AcRx::kInitAppMsg:
acrxDynamicLinker->unlockApplication(appId);
acrxDynamicLinker->registerAppMDIAware(appId);
initApp();
break;
case AcRx::kUnloadAppMsg:
unloadApp();
}
return AcRx::kRetOK;
}

[/code]

 

This classic sample is from ObjectARX SDK samples\entity\tempapp_dg. Attachment is the picture showing gripping a custom point ( index number 100) to the center of the circle. 

 

0 Likes
Reply
414 Views
0 Replies
Replies (0)

Type a product name