1. 程式人生 > >【CAD二次開發】-ObjectARX-擴充套件資料 (Xdata)

【CAD二次開發】-ObjectARX-擴充套件資料 (Xdata)

基本思路:

(1)建立一個新專案,命名為Xdata.註冊一個命令AddXData.

實現程式碼為:

static void AAAMyGroupAddXData() {
		// 提示使用者選擇所要新增擴充套件資料的圖形物件
		AcDbEntity *pEnt = NULL;
		AcGePoint3d pickPoint;
		if (CSelectUtil::PromptSelectEntity(TEXT("\n選擇所要新增的擴充套件資料的實體:"),
			AcDbEntity::desc(),pEnt,pickPoint))
		{
			CString appName = TEXT("XDataApp");

			//註冊應用程式名稱
			acdbRegApp(appName);

			//建立結果緩衝區連結串列
			struct resbuf* rb = acutBuildList(AcDb::kDxfRegAppName, appName,
				//應用程式名稱
				AcDb::kDxfXdAsciiString, TEXT("字串測試資料"),//字元創
				AcDb::kDxfXdInteger32, 2,//整數
				AcDb::kDxfXdReal, 3.14,//實數
				AcDb::kDxfXdWorldXCoord, asDblArray(pickPoint),//點座標值
				RTNONE);

			//為選擇的實體新增擴充套件資料
			pEnt->setXData(rb);
			acutRelRb(rb);

			acutPrintf(TEXT("\n成功為實體添加了擴充套件資料."));
			pEnt->close();
		}

	}
	// Modal Command with pickfirst selection
	// ACED_ARXCOMMAND_ENTRY_AUTO(CXdataApp, AAAMyGroup, MyPickFirst, MyPickFirstLocal, ACRX_CMD_MODAL | ACRX_CMD_USEPICKSET)
	static void AAAMyGroupMyPickFirst () {
		ads_name result ;
		int iRet =acedSSGet (ACRX_T("_I"), NULL, NULL, NULL, result) ;
		if ( iRet == RTNORM )
		{
			// There are selected entities
			// Put your command using pickfirst set code here
		}
		else
		{
			// There are no selected entities
			// Put your command code here
		}
	}

 建立一個類CSelectUtil,實現函式PromptSelectEntity:

函式宣告:

	// 提示使用者選擇某個型別的實體
	// 注意:呼叫者必須關閉實體	
	static bool PromptSelectEntity(const TCHAR* prompt, AcRxClass* classDesc, AcDbEntity *&pEnt, AcGePoint3d &pickPoint,
		bool bOpenForWrite = true);
	static bool PromptSelectEntity(const TCHAR* prompt, const std::vector<AcRxClass*> &classDescs, AcDbEntity *&pEnt,
		AcGePoint3d &pickPoint, bool bOpenForWrite = true);

函式實現: 

bool CSelectUtil::PromptSelectEntity(const TCHAR* prompt, AcRxClass* classDesc, AcDbEntity *&pEnt,
	AcGePoint3d &pickPoint, bool bOpenForWrite /*= true*/)
{
	std::vector<AcRxClass*> descs;
	descs.push_back(classDesc);

	return PromptSelectEntity(prompt, descs, pEnt, pickPoint, bOpenForWrite);
}

bool CSelectUtil::PromptSelectEntity(const TCHAR* prompt, const std::vector<AcRxClass*> &classDescs, AcDbEntity *&pEnt,
	AcGePoint3d &pickPoint, bool bOpenForWrite/*= true*/ )
{
	ads_name ename;
RETRY:
	if (acedEntSel(prompt, ename, asDblArray(pickPoint)) != RTNORM)
	{
		pEnt = NULL;
		return false;
	}

	AcDbObjectId entId;
	acdbGetObjectId(entId, ename);

	// 判斷選擇的實體是否是指定型別的實體
	Acad::ErrorStatus es;
	if (bOpenForWrite)
	{
		es = acdbOpenObject(pEnt, entId, AcDb::kForWrite);
	}
	else
	{
		es = acdbOpenObject(pEnt, entId, AcDb::kForRead);
	}
	assert(es == Acad::eOk);
	bool bRet = false;
	for (int i = 0; i < (int)classDescs.size(); i++)
	{
		if (pEnt->isKindOf(classDescs[i]))
		{
			bRet = true;
			break;
		}
	}

	if (bRet)
	{
		return true;
	}
	else
	{
		pEnt->close();
		acutPrintf(TEXT("\n選擇的實體型別不合要求, 請再次選擇..."));
		goto RETRY;
	}
}


(2)註冊一個ViewXData命令,用於檢視指定的實體的擴充套件資料。

實現函式為:

static void AAAMyGroupViewXData() {
		//提示使用者選擇所要檢視擴充套件資料的圖形物件
		AcDbEntity *pEnt = NULL;
		AcGePoint3d pickPoint;
		if (CSelectUtil::PromptSelectEntity(TEXT("\n選擇所要新增擴充套件資料的實體:"), AcDbEntity::desc(), pEnt, pickPoint))
		{
			CString appName = TEXT("XDataApp");

			//獲取實體的擴充套件資料
			struct resbuf *pRb = pEnt->xData(appName);
			if (pRb != NULL)
			{
				//在命令列顯示所有的擴充套件資料
				struct resbuf *pTemp = pRb; //使用臨時的結果緩衝區指標進行
				                            //遍歷,pRb不修改便於釋放
				//首先要跳過資料名稱這一項
				pTemp = pTemp->rbnext;
				acutPrintf(TEXT("\n字串型別的擴充套件資料是:%s"), pTemp->resval.rstring);

				pTemp = pTemp->rbnext;
				acutPrintf(_T("\n整數型別的擴充套件資料是:%d"), pTemp->resval.rint);

				pTemp = pTemp->rbnext;
				acutPrintf(TEXT("\n實數型別的擴充套件資料是:%.2f"), pTemp->resval.rreal);

				pTemp = pTemp->rbnext;
				acutPrintf(TEXT("\n點座標的資料型別的擴充套件資料是:(%.2f,%.2f,%.2f)"),
					pTemp->resval.rpoint[X], pTemp->resval.rpoint[Y],
					pTemp->resval.rpoint[Z]);

				acutRelRb(pRb);
			}
			else
			{
				acutPrintf(TEXT("\n所選擇的實體不包含任何的擴充套件資料!"));
			}
			pEnt->close();
		}

	}

(3)註冊新命令DeleteXData,用於從實體中刪除特定的擴充套件資料.

實現程式碼:

static void AAAMyGroupDeleteXData() {
		//提示使用者選擇所要刪除擴充套件資料的圖形物件
		AcDbEntity *pEnt = NULL;
		AcGePoint3d pickPoint;
		if (CSelectUtil::PromptSelectEntity(TEXT("\n選擇所要刪除擴充套件資料的實體:"),
			AcDbEntity::desc(),pEnt,pickPoint))
		{
			CString appName = TEXT("XDataApp");
			//註冊應用程式名稱
			acdbRegApp(appName);

			//建立結果緩衝區連結串列
			struct resbuf *rb = acutBuildList(AcDb::kDxfRegAppName, appName, RTNONE);
			//應用程式名稱

			//設定內容為空的結果緩衝區連結串列就是刪除擴充套件資料
			pEnt->setXData(rb);
			acutRelRb(rb);

			acutPrintf(TEXT("\n成功為實體刪除了擴充套件資料."));

			pEnt->close();
		}

	}

完整的專案程式碼:

效果:

①先建立兩條直線,執行AddXData命令,選擇其中一條直線,為其新增擴充套件資料;

②執行ViewXData命令,檢視擴充套件資料

③執行DeleteXData命令,刪除擴充套件命令。

Reference:

張帆《AutoCAD ObjectARX(VC)開發基礎與例項教程》