draworder - an problem by select objects

draworder - an problem by select objects

jan_tappenbeck
Collaborator Collaborator
825 Views
3 Replies
Message 1 of 4

draworder - an problem by select objects

jan_tappenbeck
Collaborator
Collaborator

hi !

 

i want to create a draworder-function with a subfunction to select object by layer-filter.

 

the function to select the elements is following:

 

 Public Function GetEntitiesOnLayer(layerName As String) As ObjectIdCollection
        ' http://ma22-wiki-001/eblwiki/index.php?title=Acad_(Klasse_von_EBL.Service)#GetEntitiesOnLayer
        ' Quelle: http://through-the-interface.typepad.com/through_the_interface/2008/05/finding-all-the.html
        Dim doc As Document = Application.DocumentManager.MdiActiveDocument
        Dim ed As Editor = doc.Editor
        ' Build a filter list so that only entities
        ' on the specified layer are selected
        Dim tvs As TypedValue() = New TypedValue(0) {New TypedValue(CInt(DxfCode.LayerName), layerName)}
        Dim sf As New SelectionFilter(tvs)
        Dim psr As PromptSelectionResult = ed.SelectAll(sf)

        If psr.Status = PromptStatus.OK Then
            Return New ObjectIdCollection(psr.Value.GetObjectIds())
        Else
            Return New ObjectIdCollection()
        End If
    End Function

 

the draworder-main function is:

 

 ''' <summary>
    ''' ändern der Zeichenreihenfolge - HINTERgrund
    ''' </summary>
    ''' <param name="LayerFilter">Filter für die Layernamen</param>
    ''' <param name="Log">optional byref Log (default:= LEERSTRING)</param>
    ''' <returns>true ... ok / false ....mit Fehler</returns>
    Public Function DrawOrderChangeToButtom(ByVal LayerFilter As String, Optional ByRef Log As String = "") As Boolean
        _Editor.WriteMessage("Objekte in den Hintergrund verschieben ...")
        DrawOrderChange_Work(LayerFilter, 0, Log)
    End Function
    ''' <summary>
    ''' ändern der Zeichenreihenfolge - VORDERgrund
    ''' </summary>
    ''' <param name="LayerFilter">Filter für die Layernamen</param>
    ''' <param name="Log">optional byref Log (default:= LEERSTRING)</param>
    ''' <returns>true ... ok / false ....mit Fehler</returns>
    Public Function DrawOrderChangeToTop(ByVal LayerFilter As String, Optional ByRef Log As String = "") As Boolean
        _Editor.WriteMessage("Objekte in den Vordergrund verschieben ...")
        DrawOrderChange_Work(LayerFilter, 1, Log)
    End Function
    ''' <summary>
    ''' ändern der Zeichenreihenfolge - Arbeitsfunktion
    ''' </summary>
    ''' <param name="LayerFilter">Filter für die Layernamen</param>
    ''' <param name="Status">0 .... 2Buttom / 1 ... 2Top</param>
    ''' <param name="Log">optional byref Log (default:= LEERSTRING)</param>
    ''' <returns>true ... ok / false ....mit Fehler</returns>
    Private Function DrawOrderChange_Work(ByVal LayerFilter As String, ByVal Status As Short, Optional ByRef Log As String = "") As Boolean

        AcReInit()
        Dim Obj2Move As ObjectIdCollection = GetEntitiesOnLayer(LayerFilter)
        Dim drawOrder As New SortedList(Of Long, ObjectId)()

        If LayerFilter.Length = 0 Then
            Log += "kein Layerfilter angegeben!"
            Return False
        End If

        Dim Msg As String = "keine Objekte gefiltert!"
        If Obj2Move.Count = 0 Then
            _Editor.WriteMessage(Msg)
            Log += Msg
            Return True
        End If

        Msg = "Anzahl gefilterter Objekte: " & Obj2Move.Count.ToString
        _Editor.WriteMessage(Msg)
        Log += Msg

        Try
            Using tr As Transaction = _Database.TransactionManager.StartTransaction()

                Dim bt As BlockTable = TryCast(tr.GetObject(_Database.BlockTableId, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForRead), BlockTable)
                Dim btrModelSpace As BlockTableRecord = TryCast(tr.GetObject(bt(BlockTableRecord.ModelSpace), Autodesk.AutoCAD.DatabaseServices.OpenMode.ForRead), BlockTableRecord)
                Dim dot As DrawOrderTable = TryCast(tr.GetObject(btrModelSpace.DrawOrderTableId, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForWrite), DrawOrderTable)
                Dim objToMove As New ObjectIdCollection()

                ''For i As Integer = 0 To Obj2Move.Count - 1
                ''    objToMove.Add(Obj2Move(i))
                ''Next i

                Select Case Status
                    Case 0
                        dot.MoveToBottom(Obj2Move)
                    Case 1
                        dot.MoveToTop(Obj2Move)

                End Select

                tr.Commit()
            End Using

        Catch ex As Exception
            Log += "unerwarteter Fehler in EBL.Service > Acad > DrawOrder" & vbCrLf & ex.ToString
            Return False
        End Try

        Return True
    End Function

 

the problem is to select the objects.

 

if i call GetEntitiesOnLayer by a text-call

 

    <LispFunction("EBL_SEL")> _
    Public Sub EBL_SEL(ByVal rbArgs As ResultBuffer)
        GetEntitiesOnLayer("Grün")
    End Sub

it works!

 

 

if i call the draworder-function there is in line

If psr.Status = PromptStatus.OK Then

of GetEntitiesOnLayer

 

psr.Status = Error {-5001}

 

could someone tell me why?

 

reagards Jan

0 Likes
Accepted solutions (1)
826 Views
3 Replies
Replies (3)
Message 2 of 4

_gile
Consultant
Consultant

Hi,

 

I'm not sure to fully understand the question, but I saw some things in the code you should pay attention to.

 

Your GetEntitiesOnLayer() method returns an ObjectIdCollection instance. AFAIK there's no LISP equivalent to this type.

Your LispFunction should return a ResultBuffer which will be converted into a LISP list.

 

Another thing, the DrawOrderTable is related to a specific BlockTableRecord (ModelSpace in your code) so, your SelectionFilter should also filter the space.

 

        public ObjectIdCollection GetEntititesOnLayer(string layerPattern)
        {
            var ed = AcAp.DocumentManager.MdiActiveDocument.Editor;
            var psr = ed.SelectAll(new SelectionFilter(
                new[] { new TypedValue(8, layerPattern), new TypedValue(410, "Model") }));
            if (psr.Status == PromptStatus.OK)
                return new ObjectIdCollection(psr.Value.GetObjectIds());
            return new ObjectIdCollection();
        }

        [LispFunction("EBL_SEL")]
        public ResultBuffer EBL_SEL(ResultBuffer resbuf)
        {
            var ids = GetEntititesOnLayer("0");
            if (ids.Count == 0)
                return null;
            var retVal = new ResultBuffer();
            foreach (ObjectId  id in ids)
            {
                retVal.Add(new TypedValue((int)LispDataType.ObjectId, id));
            }
            return retVal;
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 3 of 4

jan_tappenbeck
Collaborator
Collaborator
Hi!

thanks, but EBL_SEL is only a test call to check if the selction works outside the draworder funktion.

Jan
0 Likes
Message 4 of 4

_gile
Consultant
Consultant
Accepted solution

This seems to work for me.

 

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;

namespace DrawOrderByLayer
{
    public class Commands
    {
        enum MoveDrawOrder { ToBottom, ToTop }

        [CommandMethod("LAYERTOTOP")]
        public void SetLayerToTop()
        {
            DrawOrderByLayer(GetEntititesOnLayer(), MoveDrawOrder.ToTop);
        }

        [CommandMethod("LAYERTOBOTTOM")]
        public void SetLayerToBottom()
        {
            DrawOrderByLayer(GetEntititesOnLayer(), MoveDrawOrder.ToBottom);
        }

        private ObjectIdCollection GetEntititesOnLayer()
        {
            var ed = Application.DocumentManager.MdiActiveDocument.Editor;
            var pso = new PromptStringOptions("\nEnter the layer name: ");
            pso.AllowSpaces = true;
            var pr = ed.GetString(pso);
            if (pr.Status != PromptStatus.OK)
                return null;
            var layerName = pr.StringResult;
            if (string.IsNullOrWhiteSpace(layerName))
                return null;
            var psr = ed.SelectAll(new SelectionFilter(
                new[] { new TypedValue(8, layerName), new TypedValue(410, "Model") }));
            if (psr.Status != PromptStatus.OK)
            {
                ed.WriteMessage($"\nNone object found on layer: {layerName}");
                return null;
            }
            return new ObjectIdCollection(psr.Value.GetObjectIds());
        }

        private void DrawOrderByLayer(ObjectIdCollection ids, MoveDrawOrder order)
        {
            if (ids == null) return;
            var db = HostApplicationServices.WorkingDatabase;
            using (var tr = db.TransactionManager.StartTransaction())
            {
                var ms = (BlockTableRecord)tr.GetObject(
                    SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
                var dot = (DrawOrderTable)tr.GetObject(ms.DrawOrderTableId, OpenMode.ForWrite);
                if (order == MoveDrawOrder.ToBottom)
                    dot.MoveToBottom(ids);
                else
                    dot.MoveToTop(ids);
                tr.Commit();
            }
        }
    }
}


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub