Тема: Работа со слоями с помощью Transaction на vb.net параметр IsFrozen

Работая со слоями я столкнулся с ещё одной небольшой проблемой
вот процедура замораживающая или размораживающая слои в зависимости от их состояния по нажатии на кнопку

    Private Sub btnLayersON_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLayersON.Click
        Try
            Dim doc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
            Dim db As Database = doc.Database
            Dim ed As Editor = doc.Editor
            Using lock As DocumentLock = doc.LockDocument()
                Using tr As Transaction = db.TransactionManager.StartTransaction()
                    Dim acLyrTbl As LayerTable = TryCast(tr.GetObject(db.LayerTableId, OpenMode.ForRead), LayerTable)
                    For Each objId As ObjectId In acLyrTbl
                        Dim acLyrTblRec As LayerTableRecord = TryCast(tr.GetObject(objId, OpenMode.ForWrite), LayerTableRecord)
                        If acLyrTblRec.ObjectId <> db.Clayer Then
                            If acLyrTblRec.IsFrozen = False Then
                                acLyrTblRec.IsFrozen = True
                            Else
                                acLyrTblRec.IsFrozen = False
                            End If
                        End If
                    Next
                    tr.Commit()
                End Using
            End Using
            ed.UpdateScreen()
        Catch ex As Autodesk.AutoCAD.Runtime.Exception
         Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(vbLf + ex.Message)
        End Try
    End Sub

но при разморозки слоев они не отображаются хотя фактически разморозка произошла это же подтверждает и менеджер слоев
мне удалось добиться отображения слоев с помощью команды
ed.Regen()
но согласитесь это не выход

не пойму чего же не хватает??

(изменено: Александр Ривилис, 19 декабря 2010г. 15:08:21)

Re: Работа со слоями с помощью Transaction на vb.net параметр IsFrozen

Artem A пишет:

мне удалось добиться отображения слоев с помощью команды ed.Regen() но согласитесь это не выход

Именно это и есть выход. Отключенные и замороженные слои именно тем и отличаются, что первые достаточно включить, а для вторых требуется регенерация.

Re: Работа со слоями с помощью Transaction на vb.net параметр IsFrozen

хм но в большом файле это будет реальной проблемой, да и встроенный диспетчер свойств слоев делает это значительно быстрее....

Re: Работа со слоями с помощью Transaction на vb.net параметр IsFrozen

Artem A пишет:

да и встроенный диспетчер свойств слоев делает это значительно быстрее....

А вот это очень странно.
P.S.: В чистом ObjectARX есть функция:

Acad::ErrorStatus applyCurDwgLayerTableChanges();

которая без полной регенерации обновляет состояние слоев.
Ее можно вызвать через P/Invoke из .NET

Re: Работа со слоями с помощью Transaction на vb.net параметр IsFrozen

да, до этого уровня мне ещё нужно дорасти понял лишь что это
скорее всего это "?applyCurDwgLayerTableChanges@@YA?AW4ErrorStatus@Acad@@XZ"

вызывается примерно как то так
Private Declare Auto Function applyCurDwgLayerTableChanges Lib "acad.exe" Alias "?applyCurDwgLayerTableChanges@@YA?AW4ErrorStatus@Acad@@XZ"

но как всем этим пользоваться на второй неделе погружения в .net мне не осилить

(изменено: Александр Ривилис, 20 декабря 2010г. 00:30:42)

Re: Работа со слоями с помощью Transaction на vb.net параметр IsFrozen

Artem A пишет:

вызывается примерно как то так Private Declare Auto Function applyCurDwgLayerTableChanges Lib "acad.exe" Alias "?applyCurDwgLayerTableChanges@@YA?AW4ErrorStatus@Acad@@XZ"

Это не вызывается, а определяется (декларируется). Да и декларация не верна. Должно быть как-то так:

<DllImport("acad.exe", EntryPoint:="?acdbApplyCurDwgLayerTableChanges@@YAXXZ")> _
Private Shared Sub applyCurDwgLayerTableChanges()
End Sub

А вызывается:

applyCurDwgLayerTableChanges()

где-нибудь вместо ed.Regen()

(изменено: Artem A, 20 декабря 2010г. 11:29:46)

Re: Работа со слоями с помощью Transaction на vb.net параметр IsFrozen

Вот что у меня получилось.
но все же значительно медленней чем через диспетчер свойств слоев, практически та же регенерация

код vb.net

    <DllImport("acad.exe", CharSet:=CharSet.Unicode, CallingConvention:=CallingConvention.Cdecl, EntryPoint:="?acedRegenLayers@@YGXABV?$AcArray@VAcDbObjectId@@V?$AcArrayMemCopyReallocator@VAcDbObjectId@@@@@@H@Z")> _
    Private Shared Sub acedRegenLayers(ByVal pointer As IntPtr, ByVal num As Integer)
    End Sub
    Public Shared Sub RegenLayers(ByVal objectids As ObjectIdCollection, ByVal num As Integer)
        acedRegenLayers(objectids.UnmanagedObject, num)
    End Sub

И по нажатию на кнопку

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim objectIds As New ObjectIdCollection()
        Dim doc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        Dim db As Database = doc.Database
        Using tr As Transaction = db.TransactionManager.StartTransaction()
            Dim acLyrTbl As LayerTable = tr.GetObject(db.LayerTableId, OpenMode.ForRead)
            For Each objId As ObjectId In acLyrTbl
                objectIds.Add(objId)
            Next
        End Using
        RegenLayers(objectIds, 0)
    End Sub

Re: Работа со слоями с помощью Transaction на vb.net параметр IsFrozen

Ну вообще-то это не та функция... Она должна регенерировать только те объекты, которые находятся на замораживаемых/размораживаемых слоях. Если же ты обрабатываешь сразу все слои, то это и будет полная регенерация.

Re: Работа со слоями с помощью Transaction на vb.net параметр IsFrozen

ах ну конечно, ну тогда вот так

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim objectIds As New ObjectIdCollection()
        Dim doc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        Dim db As Database = doc.Database
        Using lock As DocumentLock = doc.LockDocument()
            Using tr As Transaction = db.TransactionManager.StartTransaction()
                Dim acLyrTbl As LayerTable = tr.GetObject(db.LayerTableId, OpenMode.ForRead)
                For Each objId As ObjectId In acLyrTbl
                    Dim acLyrTblRec As LayerTableRecord = TryCast(tr.GetObject(objId, OpenMode.ForWrite), LayerTableRecord)
                    If acLyrTblRec.IsFrozen Then acLyrTblRec.IsFrozen = False : objectIds.Add(objId)
                Next
                tr.Commit()
            End Using
        End Using
        RegenLayers(objectIds, 0)
    End Sub

и со скоростью порядок
спасибо! :)

интересно что означает число в записи RegenLayers(objectIds, 0)?

Re: Работа со слоями с помощью Transaction на vb.net параметр IsFrozen

Вообще-то это недокументированная функция. Точнее их две:

void __stdcall acedRegenLayers(class AcArray<class AcDbObjectId,class AcArrayMemCopyReallocator<class AcDbObjectId> > const &,int);
void __stdcall acedRegenLayers(class AcArray<class AcDbObjectId,class AcArrayMemCopyReallocator<class AcDbObjectId> > const &,int,int);

Описания не нашел.

Re: Работа со слоями с помощью Transaction на vb.net параметр IsFrozen

Кстати для ребят которые начинают писать под x64 код импорта dll будет таким

<DllImport("acad.exe", CharSet:=CharSet.Unicode, CallingConvention:=CallingConvention.Cdecl, EntryPoint:="?acedRegenLayers@@YAXAEBV?$AcArray@VAcDbObjectId@@V?$AcArrayMemCopyReallocator@VAcDbObjectId@@@@@@H@Z")> _

все остальное без изменений