Тема: Draworder программно

Привет!
Есть ли способ программно реализовать механизм команды DRAWORDER?
Спасибо!

Re: Draworder программно

Можно. Правда, для этого используется недокументированный класс AcDbSortentsTable.

Re: Draworder программно

А как, простите, его использовать?
Я дал поиск "AcDbSortentsTable" по папке с ObjectArx, оно нашлось в acdb15.lib. Че делать дальше, пока не придумал. А где обычно берется информация о недокументированных классах? :)

Re: Draworder программно

Приведу решение в этом форуме (оно есть на англоязычных форумах, так что приводится для экономии вашего времени).
Нужно создать и включить в проект три файла (см.ниже).
Вызов собственно функции, отправляющей примитив на задний план:

AcDbObjectId imageId = pAcDbRasterImage->objectId();
pAcDbRasterImage->close();        
pAcDbRasterImage = NULL;
pModel->close();
pModel = NULL;
MoveToBottom(imageId);

Попытка отправить на задний план объекты, открытые на запись, приводит к тому, что вызов не работает, поскольку примитив и его владелец при выполнении вызова открываются на чтение.
Итак, файлы:
sorttab.h

#ifndef ACDB_SORTTAB_H
#define ACDB_SORTTAB_H
#include "dbmain.h"
class AcDbImpSortentsTable;
class AcDbSortentsTable : public AcDbObject
{
public:
ACRX_DECLARE_MEMBERS(AcDbSortentsTable);
AcDbSortentsTable();
virtual ~AcDbSortentsTable();
Adesk::Boolean sortAs(AcDbObjectId, cDbHandle&) const;
Acad::ErrorStatus remove(AcDbObjectId);
Acad::ErrorStatus moveToBottom(AcDbObjectIdArray& ar);
Acad::ErrorStatus moveToTop(AcDbObjectIdArray& ar);
Acad::ErrorStatus moveBelow(AcDbObjectIdArray& ar, AcDbObjectId target);
Acad::ErrorStatus moveAbove(AcDbObjectIdArray& ar, AcDbObjectId target);
Acad::ErrorStatus swapOrder(AcDbObjectId, AcDbObjectId);
Acad::ErrorStatus setBlockId(AcDbObjectId);
AcDbObjectId blockId() const;
// Overridden AcDbObject members
//
virtual Acad::ErrorStatus applyPartialUndo(AcDbDwgFiler*, AcRxClass*);
virtual Acad::ErrorStatus dwgInFields(AcDbDwgFiler*);
virtual Acad::ErrorStatus dwgOutFields(AcDbDwgFiler*) const;
virtual Acad::ErrorStatus dxfInFields(AcDbDxfFiler*);
virtual Acad::ErrorStatus dxfOutFields(AcDbDxfFiler*) const;
private:
AcDbImpSortentsTable* mpImpObj;
};
#endif // ACDB_SORTTAB_H

sortens.h

#include "sorttab.h"
AcDbSortentsTable* get_sortents_table_of(AcDbEntity *pEnt);
void setSortentsBits( int bits );
void configureSortents();
void MSSendBack(AcDbObjectId ent_id);

sortens.cpp

#include "StdAfx.h"
#include "sorttab.h"
#include "Sortens.h"
AcDbSortentsTable* get_sortents_table_of(AcDbEntity *pEnt)
    {
    AcDbObjectId owner_id = pEnt->ownerId();
    if (AcDbObjectId::kNull == owner_id)
        return NULL;
    AcDbBlockTableRecord *pRec;
    Acad::ErrorStatus errSt = acdbOpenObject( pRec, owner_id, AcDb::kForRead );
    if (Acad::eOk != errSt)
        {
        // LogError("Не удалось отправить примитив на задний план. Ошибка открытия BTR. Код " + MyString(errSt) + ".")
        return NULL;
        }
        
    AcDbObjectId ext_id = pRec->extensionDictionary();
    if (AcDbObjectId::kNull == ext_id)
        {
        if (Acad::eOk != pRec->upgradeOpen())
            {
            pRec->close();
            return NULL;
            }
        pRec->createExtensionDictionary();
        ext_id = pRec->extensionDictionary();
        if (AcDbObjectId::kNull == ext_id)
            {
            pRec->close();
            return NULL;
            }
        }
    AcDbDictionary *pExt;
    Acad::ErrorStatus es = acdbOpenObject( pExt, ext_id, AcDb::kForRead );
    pRec->close();
    if (Acad::eOk != es)
        return NULL;
    AcDbObject *pObj;
    if (Acad::eOk != pExt->getAt( "ACAD_SORTENTS", pObj, AcDb::kForWrite ))
        {
        if (Acad::eOk != pExt->upgradeOpen())
            {
            pExt->close();
            return NULL;
            }
        AcDbSortentsTable *pSt = new AcDbSortentsTable;
        if (NULL == pSt)
            {
            pExt->close();
            return NULL;
            }
        AcDbObjectId new_id;
        if (Acad::eOk != pExt->setAt( "ACAD_SORTENTS", pSt, new_id ))
            {
            delete pSt;
            pExt->close();
            return NULL;
            }
        pSt->setBlockId( owner_id );
        pObj = pSt;
        }
    pExt->close();
    if (!pObj->isKindOf( AcDbSortentsTable::desc() ))
        {
        pObj->close();
        return NULL;
        }
    return (AcDbSortentsTable*)pObj;
    }
void setSortentsBits( int bits )
    {
    resbuf rb;
    rb.restype = RTSHORT;
    rb.resval.rint = bits;
    acedSetVar( "SORTENTS", &rb );
    }
void configureSortents()
    {
    resbuf rb;
    const int nSortentsMask = (1 | 2 | 4 | 8 | 16 | 32 | 64);
    acedGetVar( "SORTENTS", &rb );
    if (nSortentsMask != (rb.resval.rint & nSortentsMask))
        setSortentsBits( rb.resval.rint | nSortentsMask );
    }
void MSSendBack(AcDbObjectId ent_id)
    {
    configureSortents();
    AcDbEntity *pEnt;
    Acad::ErrorStatus errSt = acdbOpenObject( pEnt, ent_id, AcDb::kForRead );
    if (Acad::eOk != errSt)
        {
        // LogError("Не удалось отправить примитив на задний план. Ошибка открытия объекта. Код " + MyString(errSt) + ".")
        return;
        }        
    AcDbSortentsTable *pSt = get_sortents_table_of( pEnt );
    pEnt->close();
    if (NULL == pSt)
        return;
    AcDbObjectIdArray entity_array;
    entity_array.append( ent_id );
    pSt->moveToBottom(entity_array);
    pSt->close();
    }

Все это [после некоторой отладки] прекрасно завелось под VS 2003, objectARX 2000.