Changing draworder of entities

By Balaji Ramamoorthy

An MText with background mask set can hide entities that are behind it. To send the MText to the back and make the entity behind it to be visible, we can set the DrawOrder in AutoCAD using the context menu option. This can also be achieved programmatically for an entity.

Here is a sample code to send a selected entity behind. i.e., change the draworder of the selected entity to bottom.

Using ObjectARX :

static void ADSProjectSendToBottom(void)
{
    ads_name ent;
    ads_point pt;
 
    Acad::ErrorStatus es;
    int ret = RTNORM;
    ret = acedEntSel(    _T("nSelect Entity: "), 
                ent,
                pt
              );
 
    if (RTNORM != ret)
        return;
 
    AcDbObjectId ent_id;
    if (Acad::eOk != acdbGetObjectId( ent_id, ent ))
        return;
 
    configureSortents();
 
    AcDbEntity *pEnt;
    es = acdbOpenObject( pEnt, ent_id, AcDb::kForRead );
    if (Acad::eOk != es)
        return;
 
    AcDbSortentsTable *pSt = GetSortentsTableOf( pEnt );
 
    pEnt->close();
    if (NULL == pSt)
        return;
 
    AcDbObjectIdArray entity_array;
    entity_array.append( ent_id );
 
    pSt->moveToBottom( entity_array );
    pSt->close();
 
    // Send regen command or use the 
    // undocumented ads_regen method.
    acDocManager->sendStringToExecute
                            (
                                acDocManager->curDocument(),
                                L"_regenn", 
                                false, 
                                true
                            );
}

Using AutoCAD .Net API :

[CommandMethod("SendToBottom")]
public void commandDrawOrderChange()
{
    Document activeDoc 
                = Application.DocumentManager.MdiActiveDocument;
    Database db = activeDoc.Database;
    Editor ed = activeDoc.Editor;
 
    PromptEntityOptions peo 
                = new PromptEntityOptions("Select an entity : ");
    PromptEntityResult per = ed.GetEntity(peo);
    if (per.Status != PromptStatus.OK)
    {
        return;
    }
    ObjectId oid = per.ObjectId;
 
    SortedList drawOrder 
                            = new SortedList();
 
    using (Transaction tr = db.TransactionManager.StartTransaction())
    {
        BlockTable bt = tr.GetObject(    
                                        db.BlockTableId, 
                                        OpenMode.ForRead
                                    ) as BlockTable;
        BlockTableRecord btrModelSpace =
                tr.GetObject(
                                bt[BlockTableRecord.ModelSpace],
                                OpenMode.ForRead
                            ) as BlockTableRecord;
 
        DrawOrderTable dot = 
                tr.GetObject(
                                btrModelSpace.DrawOrderTableId, 
                                OpenMode.ForWrite
                            ) as DrawOrderTable;
 
        ObjectIdCollection objToMove = new ObjectIdCollection();
        objToMove.Add(oid);
        dot.MoveToBottom(objToMove);
 
        tr.Commit();
    }
    ed.WriteMessage("Done");
}

Comments

11 responses to “Changing draworder of entities”

  1. Hi Balaji!
    It specifically did you write such a complex code to ObjectARX, and so simple in C#?
    With the help of ObjectARX code can be as laconic as using C#. For example:
    static void MoveBelow(AcDbObjectId &idDown, AcDbObjectId &idUp)
    {
    AcDbSortentsTable *pSortTab = NULL;
    AcDbObjectId spaceId = AcDbObjectId::kNull;
    AcDbEntityPointer pEnt(idDown,AcDb::kForRead);
    if (pEnt.openStatus() == Acad::eOk) {
    spaceId = pEnt->ownerId();
    pEnt->close();
    }
    if (!spaceId.isNull()) {
    AcDbObjectPointer pBTR(spaceId,AcDb::kForRead);
    if (pBTR.openStatus() == Acad::eOk) {
    if (pBTR->getSortentsTable(pSortTab, AcDb::kForWrite, true) == Acad::eOk) {
    AcDbObjectIdArray ar; ar.append(idDown);
    pSortTab->moveBelow(ar,idUp);
    pSortTab->close();
    }
    }
    }
    }

  2. Balaji Avatar
    Balaji

    Hi Alexander,
    The C# sample is from my recent reply to a developer while the ObjectARX one is a bit old. I did not attempt to make them look similar. Thanks for your sample code. I will update the post.

  3. petcon Avatar
    petcon

    用点心

  4. Balaji Avatar
    Balaji

    I used Google translate and got this “用点心” = “A Snack”.
    Thanks to petcon, I am learning chinese :)

  5. Norman Yuan Avatar
    Norman Yuan

    Well, you cannot trust Google translator (or any electronic/onlne translator, for that matter) in this case.
    the cobination of the 3 Chinese characters can have different meanings, depending on the context when it is used.
    In this particular case, petcon’ really meant to ask to be more CAREFUL, or have more thought on what you were posting.
    It only means to have some snack when someone points at some snack to you.

  6. Balaji Avatar
    Balaji

    Thanks Norman :)
    I get it now, and will be careful in future.
    BTW the ObjectARX code that I posted does work. Anyway, I will be reposting the ObjectARX code to make it simpler.
    Thanks again for explaining what those 3 chinese letters meant :)

  7. Hi Balaji!
    Another idea. What about not using asynchronous sendStringToExecute method but using ads_regen function: http://adn.autodesk.com/adn/servlet/devnote?siteID=4814862&id=11845587&linkID=4900509 ?

  8. Balaji Avatar
    Balaji

    Thank you.

  9. Anonymoose Avatar
    Anonymoose

    SortedList<long, ObjectId> drawOrder = new SortedList<long, ObjectId>();
    I don’t see the SortedList used anywhere. Is there some other code missing?

  10. Eddy Lucas Avatar
    Eddy Lucas

    Thanks, i used this C# code and it worked good

  11. This code assumes you are working with AutoCAD’s ObjectARX/VLAX interface. If you are using a different programming language or API, the syntax and method calls may vary.

Leave a Reply to Alexander RivilisCancel reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading