【CAD二次开发】-ObjectARX-光标提示实体信息(EntInfoTip)

基本思路:

(1) 创建一个新工程EntInfoTip.

添加一个从AcEdInputPointMonitor类继承的类CEntInfoTipHandler.

类CEntInfoTipHandler的头文件实现代码:

class CEntInfoTipHandler :
	public AcEdInputPointMonitor
{
public:
	CEntInfoTipHandler(const bool storeInDocVars = true,AcApDocument* pDoc
	 = curDoc());
	virtual ~CEntInfoTipHandler();

	//计算需要从自动捕捉中排除的实体
	virtual bool excludeFromOsnapCalculation(const AcArray<AcDbObjectId>&
		nestedEntity, int gsSelectionMark);

	//监控输入点信息
	virtual Acad::ErrorStatus monitorInputPoint(
		bool& bAppendToTooltipStr,
		TCHAR*& pAdditionalTooltipString,
		AcGiViewportDraw* pDrawContext,
		AcApDocument* pDocument,
		bool pointComputed,
		int history,

		const AcGePoint3d& lastPoint,
		const AcGePoint3d& rawPoint,
		const AcGePoint3d& grippedPoint,
		const AcGePoint3d& cartesianSnappendPoint,
		const AcGePoint3d& osnapppendPoint,

		AcDb::OsnapMask osnapMask,
		const AcArray<AcDbCustomOsnapMode*>& customOsnapModes,
		AcDb::OsnapMask osnapOverrides,
		const AcArray<AcDbObjectId>& customOsnapOverrides,
		const AcArray<AcDbObjectId>& apertureEntitise,
		const AcArray<AcDbObjectIdArray,
		AcArrayObjectCopyReallocator<AcDbObjectIdArray>>&
		nestedApertureEntities,

		const AcArray<int>& gsSelectionMark,
		const AcArray<AcDbObjectId>& keyPointEntities,
		const AcArray<AcDbObjectIdArray,
		AcArrayObjectCopyReallocator<AcDbObjectIdArray>>&nestedKeyPointEntities,
		const AcArray<int>& keyPointGetSelectionMark,
		const AcArray<AcGeCurve3d*>& aligmentPaths,
		const AcGePoint3d& computedPoint,
		const TCHAR* pTooltipString);

private:
	//指向这个对象所属的文档
	AcApDocument* m_pDoc;
};

(2)在类CDocData的声明中添加CEntInfoTipHandler类型的成员变量:

class CDocData {

	//----- TODO: here you can add your variables

public:
	CDocData () ;
	CDocData (const CDocData &data) ;
	~CDocData () ;

	CEntInfoTipHandler* m_pIPM;
} ;

需要添加头文件:

#include "EntInfoTipHandler.h"

(3)CDocDate类的实现代码:

AsdkDataManager<CDocData> DocVars;
//----- Implementation of the document data class.
CDocData::CDocData ():m_pIPM(NULL) {
}

//-----------------------------------------------------------------------------
CDocData::CDocData (const CDocData &data):m_pIPM(NULL){
}

//-----------------------------------------------------------------------------
CDocData::~CDocData () {
	if (m_pIPM)
	{
		delete m_pIPM;
	}
}

注意:AsdkDataManager需要添加头文件:

#include "AdskDMgr.h" 

注意:要是 StdAfx.h 文件中已经定义 extern AcApDataManager<CDocData> DocVars ;  此时,DocVars已经被定义,所以你需要将 AsdkDataManager<CDocData> DocVars; 的变量名更换。

扫描二维码关注公众号,回复: 3335495 查看本文章

(4)在CEntInfoTipHandler类的构造函数中,为当前的图形文件添加输入点监视器:

CEntInfoTipHandler::CEntInfoTipHandler(const bool storeInDocVars /*= true*/,
	AcApDocument* pDoc/*= curDoc()*/)
{
	if (storeInDocVars)
	{
		assert(DocVars.docData(pDoc).m_pIPM == NULL);

		//添加输入点监视器
		m_pDoc->inputPointManager()->addPointMonitor(this);
		DocVars.docData().m_pIPM = this;
	}
	else
	{
		m_pDoc = NULL;
	}
}

在当前cpp文件的开头添加下面的语句:

extern AsdkDataManager<CDocData> DocVars;

(5)在CEntInfoTipHandler类的构造函数中,删除当前文档的输入点监视器:

CEntInfoTipHandler::~CEntInfoTipHandler()
{
	if (m_pDoc)
	{
		if (DocVars.docData(m_pDoc).m_pIPM)
		{
			//删除输入点监视器
			m_pDoc->inputPointManager()->removePointMonitor(this);
			DocVars.docData(m_pDoc).m_pIPM = NULL;
		}
	}
}

(6)excludeFromOsnapCalculation函数的实现代码:

bool CEntInfoTipHandler::excludeFromOsnapCalculation(
	const AcArray<AcDbObjectId>& nestedEntity, int gsSelectionMark)
{
	return false;
}

(7)monitorInputPoint函数的实现代码:

Acad::ErrorStatus CEntInfoTipHandler::monitorInputPoint(
	bool& bAppendToTooltipStr,
	TCHAR*& pAdditionalTooltipString,
	AcGiViewportDraw* pDrawContext,
	AcApDocument* pDocument,
	bool pointComputed,
	int history,

	const AcGePoint3d& lastPoint,
	const AcGePoint3d& rawPoint,
	const AcGePoint3d& grippedPoint,
	const AcGePoint3d& cartesianSnappendPoint,
	const AcGePoint3d& osnapppendPoint,

	AcDb::OsnapMask osnapMask,
	const AcArray<AcDbCustomOsnapMode*>& customOsnapModes,
	AcDb::OsnapMask osnapOverrides,
	const AcArray<AcDbObjectId>& customOsnapOverrides,
	const AcArray<AcDbObjectId>& apertureEntities,
	const AcArray<AcDbObjectIdArray,
	AcArrayObjectCopyReallocator<AcDbObjectIdArray>>&
	nestedApertureEntities,

	const AcArray<int>& gsSelectionMark,
	const AcArray<AcDbObjectId>& keyPointEntities,
	const AcArray<AcDbObjectIdArray,
	AcArrayObjectCopyReallocator<AcDbObjectIdArray>>&nestedKeyPointEntities,
	const AcArray<int>& keyPointGetSelectionMark,
	const AcArray<AcGeCurve3d*>& aligmentPaths,
	const AcGePoint3d& computedPoint,
	const TCHAR* pTooltipString)
{
	//一定要注意检查缓冲区的大小,避免越界导致的Acad直接跳出
	TCHAR mtooltipStr[1024], tempStr[1024];
	mtooltipStr[0] = '\0';

	Acad::ErrorStatus es;
	AcDbEntity* pEnt;
	AcDbObjectId highlightId = AcDbObjectId::kNull;

	if (pointComputed)
	{
		//分析光标所覆盖的实体
		if (apertureEntities .length() > 0)
		{
			for (int i = 0; i < apertureEntities.length(); i++)
			{
				//避免显示更多的实体(根据需要确定是否需要)
				if (i > 0)
				{
					break;
				}

				if (Acad::eOk != (acdbOpenAcDbEntity(pEnt, apertureEntities[i],
					AcDb::kForRead)))
				{
					continue;
				}

				if (pEnt->isKindOf(AcDbLine::desc()))
				{
					//实体类型信息
					if (_tcslen(mtooltipStr) > 0)
					{
						_tcscpy(mtooltipStr, TEXT("直线:"));
					}
					else
					{
						_tcscpy(mtooltipStr, TEXT("\n直线:"));
					}

					//实体详细信息
					AcDbLine* pLine = AcDbLine::cast(pEnt);
					double length = pLine->startPoint.distanceTo(pLine->
						endPoint());
					AcGeVector3d vec = pLine->endPoint() - pLine->startPoint();
					double angle = vec.convert2d(AcGePlane::kXYPlane).angle();
					_stprintf(tempStr, TEXT("\n 长度: %.2f \n 倾角 : %.2f"),
						length, RadianToAngle(angle));
				}
				else if (pEnt->isKindOf(AcDbCircle::desc()))
				{
					//实体类型信息
					if (_tcslen(mtooltipStr) > 0)
					{
						_tcscpy(mtooltipStr, TEXT("\n圆:"));
					}
					else
					{
						_tcscpy(mtooltipStr, TEXT("\n圆:"));
					}

					//实体详细信息
					AcDbCircle* pCircle = AcDbCircle::cast(pEnt);
					double radius = pCircle->radius();
					double area = PI() * radius * radius;
					_stprintf(tempStr, TEXT("\n 半径: %.2f \n面积: %.2f"),
						radius, area);
					_tcscat(mtooltipStr, tempStr);
					
				}
				pEnt->close();
			}
			highlightId = apertureEntities[0];
		}
		
	}

	//执行高亮显示,只有在显示最顶层的实体会被高亮显示
	static AcDbObjectId oldHighlightId = AcDbObjectId::kNull;
	if (highlightId != oldHighlightId)
	{
		if (AcDbObjectId::kNull != oldHighlightId)
		{
			es = acdbOpenAcDbEntity(pEnt, oldHighlightId, AcDb::kForRead);
			if (es == Acad::eOk)
			{
				es = pEnt->unhighlight();
				pEnt->close();
				oldHighlightId = AcDbObjectId::kNull;
			}
			
		}
		es = acdbOpenAcDbEntity(pEnt, highlightId, AcDb::kForRead);
		if (es == Acad::eOk)
		{
			es = pEnt->highlight();
			pEnt->close();
			oldHighlightId = highlightId;
		}
		//显示其他提示内容
		bAppendToTooltipStr = true;
		pAdditionalTooltipString = mtooltipStr;

		return Acad::eOk;
	}
}

RadianToAngle函数的实现:

double CEntInfoTipHandler::RadianToAngle(double radian)
{
	return radian * 180 / CEntInfoTipHandler::PI();
}

double CEntInfoTipHandler::PI()
{
	return atan(1.0) * 4;
}

(8)注册新命令 EntTipOn

if (!DocVars.docData().m_pIPM)
{
			new CEntInfoTipHandler;
}

添加头文件:

#include "EntInfoTipHandler.h"

别忘了声明DocVars:

// 声明这个全局函数的定义在其他的obj中
extern AsdkDataManager<CDocData> DocVars;

添加AsdkDataManager的头文件:

#include "AdskDMgr.h"

(9)注册新命令EntTipOff,关闭当前文档中实体信息动态显示的功能:

if (DocVars.docData().m_pIPM)
{
	delete DocVars.docData().m_pIPM;
	DocVars.docData().m_pIPM = NULL;
}

(10)完整项目源代码

https://pan.baidu.com/s/1GteHb7AKZiK_FSGVna35Iw

Reference:

张帆《AutoCAD ObjectARX(VC)开发基础与实例教程》

猜你喜欢

转载自blog.csdn.net/qq_40416052/article/details/82795832
今日推荐