天天看點

ObjectARX中對象句柄、ID和指針的關系一、AcDbObject對象對象的通路方式二、ID→句柄的轉換三、對象ads_name→對象ID→對象指針四、對象打開模式說明

一、AcDbObject對象對象的通路方式

在ObjectARX中,每個AcDbObject對象可以通過三種方式進行通路:

  • 通過其句柄
  • 通過其ID
  • 通過其C++執行個體指針

當AutoCAD沒有運作,圖紙儲存在檔案系統中時,可以通過句柄來辨別DWG檔案中的對象;當圖紙打開以後,圖紙資訊可通過AcDbDatabase對象進行通路。每一個資料庫中的對象擁有一個ID,其生存期持續于AcDbDatabase對象建立和删除之間的時期。打開函數(例如acdbOpenObject()函數)根據對象的ID打開對象,并傳回對象的指針。當對象關閉後,這個指針随即失效。

上述關系如下圖所示。

ObjectARX中對象句柄、ID和指針的關系一、AcDbObject對象對象的通路方式二、ID→句柄的轉換三、對象ads_name→對象ID→對象指針四、對象打開模式說明

二、ID→句柄的轉換

法1:AcDbDatabase::getAcDbObjectId(),根據對象ID值擷取其句柄。

Acad::ErrorStatus getAcDbObjectId(
	AcDbObjectId& retId, 
	bool createIfNotFound, 
    const AcDbHandle& objHandle, 
    Adesk::UInt32 xRefId = 0
);
           

法2:打開一個對象後通過getAcDbHandle()方法擷取句柄

AcDbObject* pObject;
AcDbHandle handle;
pObject->getAcDbHandle(handle);
           
請注意:打開對象以後,請盡快關閉。可以使用AcDbObject::close() 函數去關閉一個資料庫對象。

三、對象ads_name→對象ID→對象指針

ads_name和AcDbObjectId是等價的。AcDb庫提供了兩個标準函數來實作AcDbObjectId和ads_name的轉換。

// Returns an ads_name for a given object ID.
// 根據指定ID傳回其ads_name
acdbGetAdsName(ads_name& objName, AcDbObjectId objId); 

// Returns an object ID for a given ads_name.
// 根據指定ads_name傳回其ID
acdbGetObjectId(AcDbObjectId& objId, ads_name objName); 
           

通常,你是通過選擇集擷取對象,而選擇集傳回的是對象的ads_name。此時,你需要将ads_name轉換為ID值,然後利用acdbOpenObject 全局函數打開對象。

以下函數描述了這個過程

AcDbEntity*
selectEntity(AcDbObjectId& eId, AcDb::OpenMode openMode)
{
 ads_name en;
 ads_point pt;
 acedEntSel("\nSelect an entity: ", en, pt);

 // Exchange the ads_name for an object ID.
 // 更換ads_name為ID值
 acdbGetObjectId(eId, en);

 AcDbEntity * pEnt;
 acdbOpenObject(pEnt, eId, openMode);

 return pEnt;
}

           

四、對象打開模式說明

acdbOpenObject可以三種模式打開對象,分别為:

  • kForRead:如果對象沒有用kForWrite或者kForNotify方式打開,該模式可以被打開為讀模式,且最多可以被256個讀者讀取。
  • kForWrite:如果對象沒有被打開,則該模式可将對象打開為寫模式。
  • kForNotify:當對象關閉、打開為讀模式、打開為寫模式時,該模式均可以打開為通知模式。程式中極少需要将一個對象打開為通知模式。

以下表格描述了當對象打開後,再次以不同模式打開時傳回的錯誤代碼。

已經打開為 再次打開為 再次打開為 再次打開為
kForRead kForWrite kForNotify
openedForRead eAtMaxReaders (if readCount = 256; otherwise succeeds) eWasOpenForRead (Succeeds)
openedForWrite eWasOpenForWrite eWasOpenForWrite (Succeeds)
openedForNotify eWasOpenForNotify eWasOpenForNotify eWasOpenForNotify
wasNotifying (Succeeds) eWasNotifying eWasNotifying
Undo eWasOpenForUndo eWasOpenForUndo (Succeeds)

當你試圖用寫模式打開一個對象時,函數傳回錯誤提示“eWasOpenForRead”,你可以用upgradeOpen() 更新原對象的讀模式為寫模式(如果對象隻有一個讀取者)。當寫完對象以後,調用downgradeOpen()函數将對象打開模式降級為讀模式。相似的,如果對象已經以通知模式打開,但你想更新為寫模式,可以調用函數upgradeFromNotify()進行更新;當使用完畢後,調用downgradeToNotify()去降級為通知模式。

繼續閱讀