Тема: Назначить активный слой для документа

Всем добрый день!
Ребята, нужна Ваша помощь!
Встала задача в коде на VB.NET использовать ряд свойств объекта  Document из ActiveX API, такие как:
-    Document.ActiveLayer;
-    Document.ActiveLinetype;
-    Document.ActiveDimStyle;
-     и т.д.

Что-то не получается изменить ни активный слой ни текущий тип линии для документа.
В качестве примера ‘перерисовал’ пример из документации  Object Model AutoCAD:

 
'' VB.Net - Тест для определения активного слоя документа
'' с использованием свойства Document.ActiveLayer из арсенала API COM
  <CommandMethod("TestActiveLayer")> _
  Public Sub TestActiveLayer()

    ' Получение текущего документа и его база данных CAD      
    Dim curDoc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument()
    Dim curDb As Database = curDoc.Database

    Dim docCOM = Application.AcadApplication().ActiveDocument

    Dim currLayer As AcadLayer
    Dim activeLayer As String = String.Empty
    Dim previousCountLayer As Integer = 0

    '' Получаем текущий слой активного документа
    currLayer = docCOM.ActiveLayer
    activeLayer = currLayer.Name
    previousCountLayer = docCOM.Layers.Count

    '' Для проверки, получим активный слой средствами API .NET 
    Using curTrans As Transaction = curDb.TransactionManager.StartTransaction()

      '' Получаем таблицу слоёв базы данных текущего чертежа
      Dim tableLayer As LayerTable
      tableLayer = curTrans.GetObject(curDb.LayerTableId, OpenMode.ForRead)

      Dim recordTableLayer As LayerTableRecord
      recordTableLayer = curTrans.GetObject(curDb.Clayer, OpenMode.ForRead)

      MsgBox("Текущий слой - " & currLayer.Name & "   Текущий слой для контроля = " & recordTableLayer.Name & "   Количество слоев = " & previousCountLayer)

    End Using

    '' Создадим новый слой и сделаем его активным слоем
    Dim newLayer As AcadLayer
    newLayer = docCOM.Layers.Add("TestLayer")

    MsgBox("Создан новый слой - " & newLayer.Name & "   Новое количество слоев = " & docCOM.Layers.Count)

    ''Следующая строка выдает ошибку "Член группы не найден."
    docCOM.ActiveLayer = newLayer

    MsgBox("Новый активный слой - " & docCOM.ActiveLayer.Name & "   Количество слоев = " & docCOM.Layers.Count)

  End Sub

Однако при выполнении строка кода
docCOM.ActiveLayer = newLayer
выдает ошибку:
System.Runtime.InteropServices.COMException (0x80020003): Член группы не найден. (Исключение из HRESULT: 0x80020003 (DISP_E_MEMBERNOTFOUND))

Аналогичная ситуация и с заданием текущего типа линии.

Явно, что-то делаю не так!
Подскажите, пожалуйста, в чем дело, что надо сделать, чтобы изменить активный слой для документа?

Заранее благодарю за помощь.

С уважением, Андрей

(изменено: Boxa Shu, 22 июля 2013г. 17:23:39)

Re: Назначить активный слой для документа

Может попробуйте решить этот вопрос методами .NET API?
Это просто: http://docs.autodesk.com/ACD/2010/ENU/A … r=d0e36064

Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Public Class acad 
<CommandMethod("SetLayerCurrent")> _
Public Sub SetLayerCurrent()
  '' Get the current document and database
  Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
  Dim acCurDb As Database = acDoc.Database
 
  '' Start a transaction
  Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()
 
      '' Open the Layer table for read
      Dim acLyrTbl As LayerTable
      acLyrTbl = acTrans.GetObject(acCurDb.LayerTableId, _
                                   OpenMode.ForRead)
 
      Dim sLayerName As String = "Center"
 
      If acLyrTbl.Has(sLayerName) = True Then
          '' Set the layer Center current
          acCurDb.Clayer = acLyrTbl(sLayerName)
 
          '' Save the changes
          acTrans.Commit()
      End If
      '' Dispose of the transaction
  End Using
End Sub
End Class

Re: Назначить активный слой для документа

Пробуй так

Imports Autodesk.AutoCAD.Interop
Imports Autodesk.AutoCAD.Interop.Common

        '' VB.Net - Тест для определения активного слоя документа 
        '' с использованием свойства Document.ActiveLayer из арсенала API COM 
        <CommandMethod("TestActiveLayer", CommandFlags.Session)> _
        Public Sub TestActiveLayer()

            ' Получение текущего документа и его база данных CAD       
            Dim curDoc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument()
            Dim curDb As Database = curDoc.Database


            Using curTrans As Transaction = curDoc.TransactionManager.StartTransaction

                Dim docCOM = TryCast(curDoc.AcadDocument, AcadDocument)
                If docCOM Is Nothing Then Return
                '' Для проверки, получим активный слой средствами API .NET 
                Dim currLayer As AcadLayer
                Dim activeLayer As String = String.Empty
                Dim previousCountLayer As Integer = 0

                '' Получаем текущий слой активного документа 
                currLayer = docCOM.ActiveLayer
                activeLayer = currLayer.Name
                previousCountLayer = docCOM.Layers.Count



                '' Получаем таблицу слоёв базы данных текущего чертежа 
                Dim tableLayer As LayerTable
                tableLayer = curTrans.GetObject(curDb.LayerTableId, OpenMode.ForRead)

                Dim recordTableLayer As LayerTableRecord
                recordTableLayer = curTrans.GetObject(curDb.Clayer, OpenMode.ForRead)

                MsgBox("Текущий слой - " & currLayer.Name & "   Текущий слой для контроля = " & recordTableLayer.Name & "   Количество слоев = " & previousCountLayer)

                '' Создадим новый слой и сделаем его активным слоем 
                Dim acLayers As AcadLayers
                acLayers = docCOM.Layers
                Dim newLayer As AcadLayer
                newLayer = acLayers.Add("TestLayer")
                Dim acCmCol As AcadAcCmColor = docCOM.ActiveLayer.TrueColor
                acCmCol.ColorIndex = 1
                '  acLayers.GenerateUsageData() 'optional
                MsgBox("Создан новый слой - " & newLayer.Name & "   Новое количество слоев = " & docCOM.Layers.Count)
                newLayer.TrueColor = acCmCol
                ''Следующая строка не выдает ошибку "Член группы не найден." 
                docCOM.ActiveLayer = acLayers.Item("TestLayer")
                acCmCol = Nothing

                MsgBox("Новый активный слой - " & docCOM.ActiveLayer.Name & "   Количество слоев = " & docCOM.Layers.Count)
                '' dummy test for using new layer
                docCOM.SendCommand("_zoom _e _rectangle 0,0 pause ")
                curTrans.Commit()

            End Using

        End Sub

Поскольку в документе косвенным образом меняется системная переменная CLAYER,
нужно использовать CommandFlags.Session,
Ищи подробное описание этого нюанса здесь:

http://adndevblog.typepad.com/autocad/

Re: Назначить активный слой для документа

Всем добрый день!

Большое спасибо за то что откликнулись на мою просьбу и уделили мне время.
У меня стоит задача: “Получить и задать текущий/активный слой документа с использованием свойства Document.ActiveLayer из арсенала API COM “.

Пример на VBA http://vbamodel.narod.ru/AutoCAD/ex_activelayer.htm

Sub Example_ActiveLayer()
    ' Этот пример возвращает текущий слой и затем добавляет новый слой.
    ' Наконец, он возвращает слой к предыдущей установке.
    Dim currLayer As AcadLayer
    Dim newLayer As AcadLayer
    
    ' Возвратите текущий слой активного документа
    Set currLayer = ThisDrawing.ActiveLayer
    MsgBox "Текущий слой - " & currLayer.name, vbInformation, "ActiveLayer Пример"
    
    ' Создайте Слой и сделайте его активным слоем
    Set newLayer = ThisDrawing.Layers.Add("TestLayer")
    ThisDrawing.ActiveLayer = newLayer
    MsgBox "Новый слой - " & newLayer.name, vbInformation, "ActiveLayer Пример"

    ' Сбросьте слой к его предыдущей установке
    ThisDrawing.ActiveLayer = currLayer
    MsgBox "Активный слой сброшен к " & currLayer.name, vbInformation, "ActiveLayer Пример"
End Sub

Его-то я и  ‘перерисовал’ в качестве теста.

Исходя из постановки задачи, предложение Boxa Shu не подходить, но за которое большое спасибо. Проще всего эта задача решается через системную переменную CLAYER - Текущий слой. Только для чтения.
Но на практике срабатывает и
Application.SetSystemVariable("CLAYER", newLayer.Name)

Но задача стоит другая.

Олег, Вам персональное спасибо за постоянную помощь! Ваш вариант сработал. Но когда начал его более детально анализировать понял, что

Dim docCOM = Application.AcadApplication().ActiveDocument (из моего случая)

И

Dim docCOM = TryCast(curDoc.AcadDocument, AcadDocument)

Это, по-моему, не одно и тоже. По-видимому, мы опять используем интерфейс .NET, по-этому вопрос остается открытым.

Олег, может есть еще идеи?

Заранее благодарю.

С уважением, Андрей

Re: Назначить активный слой для документа

Андрей Дудинский пишет:

Олег, может есть еще идеи?

Не понял какие
Если тебе нужен чистый COM тогда не надо
использовать acmgd.dll и acdbmgd.dll,
опять же все зависит от версии и тд
Проще перейти на managed API без COM,
IMHO