(изменено: Bars, 14 января 2013г. 22:14:40)

Тема: Перемещение вхождения блока

Здравствуйте! Прошу направить стопы на правильный путь решения задачи: в чертеже есть вхождения динамического блока(ов) с пользовательскими атрибутами и параметрами - много их. Есть подключенная база данных Access.
Обнаруживаю ввод (изменение) параметра блока от пользователя (Например, Private Sub ThisDrawing_ObjectModified), затем значения параметров блока отправляюся в Access, обрабатываются и возвращаются координаты точки нового местоположения блока.
Проблема: программно переместить уже существующее вхождение блока ?
Понимаю, что будет acadThisDatabase.TransactionManager.StartTransaction, будет acadTransaction.GetObject, а так же acadBlockRef.TransformBy(Matrix3d.Displacement(acadVector3D)), но из кучи примеров для C++ (пишу на VB.NET) так и не усвоил, как же найти запись о моем экземпляре блока в базе данных чертежа, чтобы открыть его для записи ?
Прошу помочь. Очнь очнь !

Re: Перемещение вхождения блока

как же найти запись о моем экземпляре блока в базе данных чертежа

Надо знать его ObjectId

(изменено: Bars, 14 января 2013г. 22:36:39)

Re: Перемещение вхождения блока

Вот на этом то я и тормознулся: возвращаемый [Object] обработчиком события ThisDrawing_ObjectModified(ByVal [Object] As Object) путем:

Dim acadBlockRObjectId As Autodesk.AutoCAD.DatabaseServices.ObjectId = [Object]

вернет искомую величину?

Re: Перемещение вхождения блока

Почему-же? Должен быть тот

Re: Перемещение вхождения блока

Но ведь Dim acadObjectID As Autodesk.AutoCAD.DatabaseServices.ObjectId - это же целая структура, а вовсе не число типа Long... :(
Я явно чего-то недопонимэ..

Re: Перемещение вхождения блока

В ThisDrawing_ObjectModified попадает AcadObject, а не DBObject (если я правильно понял, то ты использовал COM/ActiveX а не AutoCAD .NET API), т.е. тебе нужно получить DBObject из AcadObject. В любом случае в событии ThisDrawing_ObjectModified ты не можешь модифицировать объект, который привел к событию ObjectModified - если бы это было возможно, то ты бы попал в замкнутый круг.

(изменено: Bars, 14 января 2013г. 23:24:00)

Re: Перемещение вхождения блока

Вы правильно поняли - я и так получаю "эхо" обработчика ThisDrawing_ObjectModified. Топчусь по граблям. Пожалуйста, укажите зацепку пути решения?

(изменено: Александр Ривилис, 15 января 2013г. 00:51:01)

Re: Перемещение вхождения блока

Метод (статический) Autodesk.AutoCAD.DatabaseServices.DBObject.FromAcadObject(object) позволяет получить ObjectId по AcadObject

Re: Перемещение вхождения блока

Bars пишет:

затем значения параметров блока отправляюся в Access, обрабатываются и возвращаются координаты точки нового местоположения блока.

Таким макаром, если ты вышел пообедать и потом опять
работаешь со своим проектом то скорее всего ObjectId
этого объекта не вернет тебе правильный результат, эта штука не постоянная
Хранить в базе нужно Handle объекта(строка), потом можешь конвертировать его
в нужный ObjectId
нашел пример:

Dim id As ObjectId = db.GetObjectId(False, New Handle(Int64.Parse(strHandle, Globalization.NumberStyles.AllowHexSpecifier)), 0)
Dim blkRef As BlockReference = trans.GetObject(id, OpenMode.ForWrite) 

(изменено: Bars, 15 января 2013г. 01:29:34)

Re: Перемещение вхождения блока

Александр Ривилис пишет:

Метод (статический) Autodesk.AutoCAD.DatabaseServices.DBObject.FromAcadObject(object) позволяет получить ObjectId по AcadObject

Спасибо, Александр. Сейчас испытаю. Где бы найти ссылку на доску благодарностей для Вас ?
..И Вы случайно не про этом имели ввиду:

  <Autodesk.AutoCAD.Runtime.CommandMethod("ODD_dbConnect")> _
    Public Sub ОДДdbConnect()
...
        ThisDrawing.Utility.Prompt(vbCrLf & "ОДД: база данных подключена" & vbCrLf)
        AddHandler ThisDatabaseEvents.ObjectModified, New ObjectEventHandler(AddressOf ObjectDBModified)
        'ThisDrawing.SendCommand("REGENALL" & vbCrLf)
    End Sub

    Public Sub ObjectDBModified(ByVal Sender As Object, ByVal e As Autodesk.AutoCAD.DatabaseServices.ObjectEventArgs)
        'ThisDrawing.Utility.Prompt(vbCrLf & "ОДД: обработчик событий " & e.DBObject.ObjectId.ToString() & vbCrLf)
    End Sub

(изменено: Bars, 15 января 2013г. 01:41:34)

Re: Перемещение вхождения блока

fixo пишет:

Хранить в базе нужно Handle объекта(строка), потом можешь конвертировать его
в нужный ObjectId

Да, fixo прав - это важное замечание и эту фишку про ObjectID as Long я учел: в Access ключевое поле у меня как раз и есть Handle as String, т.е. эта дыра вроде как залеплена.

Re: Перемещение вхождения блока

Теоретический вопрос остается: поскольку обработчик ActiveX/COM: ThisDrawing_ObjectModified(ByVal [Object] As Object) вызывает рекурсию модификации объектов - то как выполняить модификацию блока ? Разве транзакция не вызовет ThisDrawing_ObjectModified вновь ?

Re: Перемещение вхождения блока

Bars пишет:

Разве транзакция не вызовет ThisDrawing_ObjectModified вновь ?

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

Bars пишет:

..И Вы случайно не про этом имели ввиду:

Да. Тогда не придётся путать COM/ActiveX с .NET

Bars пишет:

Где бы найти ссылку на доску благодарностей для Вас ?

:D Есть такой реликт: https://www.caduser.ru/forum/

(изменено: Bars, 15 января 2013г. 02:13:04)

Re: Перемещение вхождения блока

Александр Ривилис пишет:

Да. Тогда не придётся путать COM/ActiveX с .NET

Попробовал завести:

   <Autodesk.AutoCAD.Runtime.CommandMethod("ODD_dbConnect")> _
    Public Sub ОДДdbConnect()
        Dim DBPath As String
        Using dlgOF As New System.Windows.Forms.OpenFileDialog
...
        ThisDrawing.Utility.Prompt(vbCrLf & "ОДД: база данных подключена" & vbCrLf)
        AddHandler ThisDatabaseEvents.ObjectModified, New ObjectEventHandler(AddressOf ObjectDBModified)
    End Sub
'Обработчик
    Private Sub ObjectDBModified(ByVal Sender As Object, ByVal e As Autodesk.AutoCAD.DatabaseServices.ObjectEventArgs)
        ThisDrawing.Utility.Prompt(vbCrLf & "ОДД: обработчик событий " & e.DBObject.ObjectId.ToString() & vbCrLf)
    End Sub

1. При выделении вхождения блока отрабатывает нормально:
ОДД: обработчик событий (8796082576224)
ОДД: обработчик событий (8796082576224)
...
2. В момент начала перетаскивания (GRIP_STRETCH) блока вываливается оное:
Application does not support just-in-time (JIT)
debugging. See the end of this message for details.
************** Exception Text **************
System.Runtime.InteropServices.COMException (0x80020009): Ошибка. (Exception from HRESULT: 0x80020009 (DISP_E_EXCEPTION))
   at Autodesk.AutoCAD.Interop.IAcadUtility.Prompt(String Message)
   at ОДД.ОДД.ObjectDBModified(Object Sender, ObjectEventArgs e) in I:\Programming\ОДД\ОДД\ОДД.vb:line 511
   at Autodesk.AutoCAD.DatabaseServices.CDatabaseReactorImpl.il_objectModified(CDatabaseReactorImpl* , AcDbDatabase* dwg, AcDbObject* obj)

Что бы это значило ?

Re: Перемещение вхождения блока

1. Будем последовательно отказываться от COM/ActiveX
2. Вместо ThisDrawing.Utility.Prompt используй Application.DocumentManager.MDIActiveDocument.Editor.WriteMessage
3. Никогда не пиши так: e.DBObject.ObjectId.ToString(),
так как ты не знаешь не равно ли e null (т.е. проверяй промежуточные значения)

(изменено: Bars, 15 января 2013г. 11:21:18)

Re: Перемещение вхождения блока

Значит я на верном пути.
Спасибо, Александр. Вы как добрый доктор - шаг за шагом отводите от навязчивой мысли, чтобы безболезненно заместить её совершенно здравой .. наступает просветление.. :)

(изменено: Bars, 15 января 2013г. 23:16:28)

Re: Перемещение вхождения блока

Александр Ривилис пишет:

1. Будем последовательно отказываться от COM/ActiveX

Не устану благодарить всех откликнувшихся и каждого лично! Осознал свои пробелы в технике и понятиях технологий программирования.
Уже сегодня переписал код с COM/ActiveX на AutoCAD.NET API и все пошло в нужном русле, открылись пространства для творчества.
Но, в продолжение сформулированной мной темы, всплыл вопрос чисто теоретический: можно ли для перемещения вхождений блоков использовать только лишь TransformBy(Matrix3d.Displacement(acadVector3D)) БЕЗ начала транзакции??? Хотя по согласно букварям AutoCAD.NET API все операции с объектами только через (гастроном  ;)) транзакцию.

Re: Перемещение вхождения блока

Bars пишет:

Но, в продолжение сформулированной мной темы, всплыл вопрос чисто теоретический: можно ли для перемещения вхождений блоков использовать только лишь TransformBy(Matrix3d.Displacement(acadVector3D)) БЕЗ начала транзакции??? Хотя по согласно букварям AutoCAD.NET API все операции с объектами только через (гастроном smile;)) транзакцию.

TransformBy можно вызывать только для открытого на запись (ForWrite) объекта. Если ты про выполнении этого метода в событии (event) ObjectModified, то нельзя.